feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,398 @@
/*
* Copyright (c) 2000, 2014, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.AWTEvent;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import sun.util.logging.PlatformLogger;
import sun.misc.ThreadGroupUtils;
/**
* This class is to let AWT shutdown automatically when a user is done
* with AWT. It tracks AWT state using the following parameters:
* <ul>
* <li><code>peerMap</code> - the map between the existing peer objects
* and their associated targets
* <li><code>toolkitThreadBusy</code> - whether the toolkit thread
* is waiting for a new native event to appear in its queue
* or is dispatching an event
* <li><code>busyThreadSet</code> - a set of all the event dispatch
* threads that are busy at this moment, i.e. those that are not
* waiting for a new event to appear in their event queue.
* </ul><p>
* AWT is considered to be in ready-to-shutdown state when
* <code>peerMap</code> is empty and <code>toolkitThreadBusy</code>
* is false and <code>busyThreadSet</code> is empty.
* The internal AWTAutoShutdown logic secures that the single non-daemon
* thread (<code>blockerThread</code>) is running when AWT is not in
* ready-to-shutdown state. This blocker thread is to prevent AWT from
* exiting since the toolkit thread is now daemon and all the event
* dispatch threads are started only when needed. Once it is detected
* that AWT is in ready-to-shutdown state this blocker thread waits
* for a certain timeout and if AWT state doesn't change during timeout
* this blocker thread terminates all the event dispatch threads and
* exits.
*/
public final class AWTAutoShutdown implements Runnable {
private static final AWTAutoShutdown theInstance = new AWTAutoShutdown();
/**
* This lock object is used to synchronize shutdown operations.
*/
private final Object mainLock = new Object();
/**
* This lock object is to secure that when a new blocker thread is
* started it will be the first who acquire the main lock after
* the thread that created the new blocker released the main lock
* by calling lock.wait() to wait for the blocker to start.
*/
private final Object activationLock = new Object();
/**
* This set keeps references to all the event dispatch threads that
* are busy at this moment, i.e. those that are not waiting for a
* new event to appear in their event queue.
* Access is synchronized on the main lock object.
*/
private final Set<Thread> busyThreadSet = new HashSet<>(7);
/**
* Indicates whether the toolkit thread is waiting for a new native
* event to appear or is dispatching an event.
*/
private boolean toolkitThreadBusy = false;
/**
* This is a map between components and their peers.
* we should work with in under activationLock&mainLock lock.
*/
private final Map<Object, Object> peerMap = new IdentityHashMap<>();
/**
* References the alive non-daemon thread that is currently used
* for keeping AWT from exiting.
*/
private Thread blockerThread = null;
/**
* We need this flag to secure that AWT state hasn't changed while
* we were waiting for the safety timeout to pass.
*/
private boolean timeoutPassed = false;
/**
* Once we detect that AWT is ready to shutdown we wait for a certain
* timeout to pass before stopping event dispatch threads.
*/
private static final int SAFETY_TIMEOUT = 1000;
/**
* Constructor method is intentionally made private to secure
* a single instance. Use getInstance() to reference it.
*
* @see AWTAutoShutdown#getInstance
*/
private AWTAutoShutdown() {}
/**
* Returns reference to a single AWTAutoShutdown instance.
*/
public static AWTAutoShutdown getInstance() {
return theInstance;
}
/**
* Notify that the toolkit thread is not waiting for a native event
* to appear in its queue.
*
* @see AWTAutoShutdown#notifyToolkitThreadFree
* @see AWTAutoShutdown#setToolkitBusy
* @see AWTAutoShutdown#isReadyToShutdown
*/
public static void notifyToolkitThreadBusy() {
getInstance().setToolkitBusy(true);
}
/**
* Notify that the toolkit thread is waiting for a native event
* to appear in its queue.
*
* @see AWTAutoShutdown#notifyToolkitThreadFree
* @see AWTAutoShutdown#setToolkitBusy
* @see AWTAutoShutdown#isReadyToShutdown
*/
public static void notifyToolkitThreadFree() {
getInstance().setToolkitBusy(false);
}
/**
* Add a specified thread to the set of busy event dispatch threads.
* If this set already contains the specified thread or the thread is null,
* the call leaves this set unchanged and returns silently.
*
* @param thread thread to be added to this set, if not present.
* @see AWTAutoShutdown#notifyThreadFree
* @see AWTAutoShutdown#isReadyToShutdown
*/
public void notifyThreadBusy(final Thread thread) {
if (thread == null) {
return;
}
synchronized (activationLock) {
synchronized (mainLock) {
if (blockerThread == null) {
activateBlockerThread();
} else if (isReadyToShutdown()) {
mainLock.notifyAll();
timeoutPassed = false;
}
busyThreadSet.add(thread);
}
}
}
/**
* Remove a specified thread from the set of busy event dispatch threads.
* If this set doesn't contain the specified thread or the thread is null,
* the call leaves this set unchanged and returns silently.
*
* @param thread thread to be removed from this set, if present.
* @see AWTAutoShutdown#notifyThreadBusy
* @see AWTAutoShutdown#isReadyToShutdown
*/
public void notifyThreadFree(final Thread thread) {
if (thread == null) {
return;
}
synchronized (activationLock) {
synchronized (mainLock) {
busyThreadSet.remove(thread);
if (isReadyToShutdown()) {
mainLock.notifyAll();
timeoutPassed = false;
}
}
}
}
/**
* Notify that the peermap has been updated, that means a new peer
* has been created or some existing peer has been disposed.
*
* @see AWTAutoShutdown#isReadyToShutdown
*/
void notifyPeerMapUpdated() {
synchronized (activationLock) {
synchronized (mainLock) {
if (!isReadyToShutdown() && blockerThread == null) {
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
activateBlockerThread();
return null;
});
} else {
mainLock.notifyAll();
timeoutPassed = false;
}
}
}
}
/**
* Determine whether AWT is currently in ready-to-shutdown state.
* AWT is considered to be in ready-to-shutdown state if
* <code>peerMap</code> is empty and <code>toolkitThreadBusy</code>
* is false and <code>busyThreadSet</code> is empty.
*
* @return true if AWT is in ready-to-shutdown state.
*/
private boolean isReadyToShutdown() {
return (!toolkitThreadBusy &&
peerMap.isEmpty() &&
busyThreadSet.isEmpty());
}
/**
* Notify about the toolkit thread state change.
*
* @param busy true if the toolkit thread state changes from idle
* to busy.
* @see AWTAutoShutdown#notifyToolkitThreadBusy
* @see AWTAutoShutdown#notifyToolkitThreadFree
* @see AWTAutoShutdown#isReadyToShutdown
*/
private void setToolkitBusy(final boolean busy) {
if (busy != toolkitThreadBusy) {
synchronized (activationLock) {
synchronized (mainLock) {
if (busy != toolkitThreadBusy) {
if (busy) {
if (blockerThread == null) {
activateBlockerThread();
} else if (isReadyToShutdown()) {
mainLock.notifyAll();
timeoutPassed = false;
}
toolkitThreadBusy = busy;
} else {
toolkitThreadBusy = busy;
if (isReadyToShutdown()) {
mainLock.notifyAll();
timeoutPassed = false;
}
}
}
}
}
}
}
/**
* Implementation of the Runnable interface.
* Incapsulates the blocker thread functionality.
*
* @see AWTAutoShutdown#isReadyToShutdown
*/
public void run() {
Thread currentThread = Thread.currentThread();
boolean interrupted = false;
synchronized (mainLock) {
try {
/* Notify that the thread is started. */
mainLock.notifyAll();
while (blockerThread == currentThread) {
mainLock.wait();
timeoutPassed = false;
/*
* This loop is introduced to handle the following case:
* it is possible that while we are waiting for the
* safety timeout to pass AWT state can change to
* not-ready-to-shutdown and back to ready-to-shutdown.
* In this case we have to wait once again.
* NOTE: we shouldn't break into the outer loop
* in this case, since we may never be notified
* in an outer infinite wait at this point.
*/
while (isReadyToShutdown()) {
if (timeoutPassed) {
timeoutPassed = false;
blockerThread = null;
break;
}
timeoutPassed = true;
mainLock.wait(SAFETY_TIMEOUT);
}
}
} catch (InterruptedException e) {
interrupted = true;
} finally {
if (blockerThread == currentThread) {
blockerThread = null;
}
}
}
if (!interrupted) {
AppContext.stopEventDispatchThreads();
}
}
@SuppressWarnings("serial")
static AWTEvent getShutdownEvent() {
return new AWTEvent(getInstance(), 0) {
};
}
/**
* Creates and starts a new blocker thread. Doesn't return until
* the new blocker thread starts.
*
* Must be called with {@link sun.security.util.SecurityConstants#MODIFY_THREADGROUP_PERMISSION}
*/
private void activateBlockerThread() {
Thread thread = new Thread(ThreadGroupUtils.getRootThreadGroup(), this, "AWT-Shutdown");
thread.setContextClassLoader(null);
thread.setDaemon(false);
blockerThread = thread;
thread.start();
try {
/* Wait for the blocker thread to start. */
mainLock.wait();
} catch (InterruptedException e) {
System.err.println("AWT blocker activation interrupted:");
e.printStackTrace();
}
}
final void registerPeer(final Object target, final Object peer) {
synchronized (activationLock) {
synchronized (mainLock) {
peerMap.put(target, peer);
notifyPeerMapUpdated();
}
}
}
final void unregisterPeer(final Object target, final Object peer) {
synchronized (activationLock) {
synchronized (mainLock) {
if (peerMap.get(target) == peer) {
peerMap.remove(target);
notifyPeerMapUpdated();
}
}
}
}
final Object getPeer(final Object target) {
synchronized (activationLock) {
synchronized (mainLock) {
return peerMap.get(target);
}
}
}
final void dumpPeers(final PlatformLogger aLog) {
if (aLog.isLoggable(PlatformLogger.Level.FINE)) {
synchronized (activationLock) {
synchronized (mainLock) {
aLog.fine("Mapped peers:");
for (Object key : peerMap.keySet()) {
aLog.fine(key + "->" + peerMap.get(key));
}
}
}
}
}
} // class AWTAutoShutdown

View File

@@ -0,0 +1,140 @@
/*
* Copyright (c) 2005, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.nio.CharBuffer;
import java.nio.ByteBuffer;
import java.nio.charset.*;
//This class delegates all invokes to the charset "javaCs" if
//its subclasses do not provide their own en/decode solution.
public class AWTCharset extends Charset {
protected Charset awtCs;
protected Charset javaCs;
public AWTCharset(String awtCsName, Charset javaCs) {
super(awtCsName, null);
this.javaCs = javaCs;
this.awtCs = this;
}
public boolean contains(Charset cs) {
if (javaCs == null) return false;
return javaCs.contains(cs);
}
public CharsetEncoder newEncoder() {
if (javaCs == null)
throw new Error("Encoder is not supported by this Charset");
return new Encoder(javaCs.newEncoder());
}
public CharsetDecoder newDecoder() {
if (javaCs == null)
throw new Error("Decoder is not supported by this Charset");
return new Decoder(javaCs.newDecoder());
}
public class Encoder extends CharsetEncoder {
protected CharsetEncoder enc;
protected Encoder () {
this(javaCs.newEncoder());
}
protected Encoder (CharsetEncoder enc) {
super(awtCs,
enc.averageBytesPerChar(),
enc.maxBytesPerChar());
this.enc = enc;
}
public boolean canEncode(char c) {
return enc.canEncode(c);
}
public boolean canEncode(CharSequence cs) {
return enc.canEncode(cs);
}
protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) {
return enc.encode(src, dst, true);
}
protected CoderResult implFlush(ByteBuffer out) {
return enc.flush(out);
}
protected void implReset() {
enc.reset();
}
protected void implReplaceWith(byte[] newReplacement) {
if (enc != null)
enc.replaceWith(newReplacement);
}
protected void implOnMalformedInput(CodingErrorAction newAction) {
enc.onMalformedInput(newAction);
}
protected void implOnUnmappableCharacter(CodingErrorAction newAction) {
enc.onUnmappableCharacter(newAction);
}
public boolean isLegalReplacement(byte[] repl) {
return true;
}
}
public class Decoder extends CharsetDecoder {
protected CharsetDecoder dec;
private String nr;
protected Decoder () {
this(javaCs.newDecoder());
}
protected Decoder (CharsetDecoder dec) {
super(awtCs,
dec.averageCharsPerByte(),
dec.maxCharsPerByte());
this.dec = dec;
}
protected CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) {
return dec.decode(src, dst, true);
}
ByteBuffer fbb = ByteBuffer.allocate(0);
protected CoderResult implFlush(CharBuffer out) {
dec.decode(fbb, out, true);
return dec.flush(out);
}
protected void implReset() {
dec.reset();
}
protected void implReplaceWith(String newReplacement) {
if (dec != null)
dec.replaceWith(newReplacement);
}
protected void implOnMalformedInput(CodingErrorAction newAction) {
dec.onMalformedInput(newAction);
}
protected void implOnUnmappableCharacter(CodingErrorAction newAction) {
dec.onUnmappableCharacter(newAction);
}
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2009, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.AWTPermission;
import sun.security.util.PermissionFactory;
/**
* A factory object for AWTPermission objects.
*/
public class AWTPermissionFactory
implements PermissionFactory<AWTPermission>
{
@Override
public AWTPermission newPermission(String name) {
return new AWTPermission(name);
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 1999, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
/**
* The AWTSecurityManager class provides the ability to secondarily
* index AppContext objects through SecurityManager extensions.
* As noted in AppContext.java, AppContexts are primarily indexed by
* ThreadGroup. In the case where the ThreadGroup doesn't provide
* enough information to determine AppContext (e.g. system threads),
* if a SecurityManager is installed which derives from
* AWTSecurityManager, the AWTSecurityManager's getAppContext()
* method is called to determine the AppContext.
*
* A typical example of the use of this class is where an applet
* is called by a system thread, yet the system AppContext is
* inappropriate, because applet code is currently executing.
* In this case, the getAppContext() method can walk the call stack
* to determine the applet code being executed and return the applet's
* AppContext object.
*
* @author Fred Ecks
*/
public class AWTSecurityManager extends SecurityManager {
/**
* Get the AppContext corresponding to the current context.
* The default implementation returns null, but this method
* may be overridden by various SecurityManagers
* (e.g. AppletSecurity) to index AppContext objects by the
* calling context.
*
* @return the AppContext corresponding to the current context.
* @see sun.awt.AppContext
* @see java.lang.SecurityManager
* @since JDK1.2.1
*/
public AppContext getAppContext() {
return null; // Default implementation returns null
}
} /* class AWTSecurityManager */

View File

@@ -0,0 +1,932 @@
/*
* Copyright (c) 1998, 2013, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.EventQueue;
import java.awt.Window;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.Toolkit;
import java.awt.GraphicsEnvironment;
import java.awt.event.InvocationEvent;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collections;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import java.util.HashSet;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyChangeListener;
import java.lang.ref.SoftReference;
import sun.util.logging.PlatformLogger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
/**
* The AppContext is a table referenced by ThreadGroup which stores
* application service instances. (If you are not writing an application
* service, or don't know what one is, please do not use this class.)
* The AppContext allows applet access to what would otherwise be
* potentially dangerous services, such as the ability to peek at
* EventQueues or change the look-and-feel of a Swing application.<p>
*
* Most application services use a singleton object to provide their
* services, either as a default (such as getSystemEventQueue or
* getDefaultToolkit) or as static methods with class data (System).
* The AppContext works with the former method by extending the concept
* of "default" to be ThreadGroup-specific. Application services
* lookup their singleton in the AppContext.<p>
*
* For example, here we have a Foo service, with its pre-AppContext
* code:<p>
* <code><pre>
* public class Foo {
* private static Foo defaultFoo = new Foo();
*
* public static Foo getDefaultFoo() {
* return defaultFoo;
* }
*
* ... Foo service methods
* }</pre></code><p>
*
* The problem with the above is that the Foo service is global in scope,
* so that applets and other untrusted code can execute methods on the
* single, shared Foo instance. The Foo service therefore either needs
* to block its use by untrusted code using a SecurityManager test, or
* restrict its capabilities so that it doesn't matter if untrusted code
* executes it.<p>
*
* Here's the Foo class written to use the AppContext:<p>
* <code><pre>
* public class Foo {
* public static Foo getDefaultFoo() {
* Foo foo = (Foo)AppContext.getAppContext().get(Foo.class);
* if (foo == null) {
* foo = new Foo();
* getAppContext().put(Foo.class, foo);
* }
* return foo;
* }
*
* ... Foo service methods
* }</pre></code><p>
*
* Since a separate AppContext can exist for each ThreadGroup, trusted
* and untrusted code have access to different Foo instances. This allows
* untrusted code access to "system-wide" services -- the service remains
* within the AppContext "sandbox". For example, say a malicious applet
* wants to peek all of the key events on the EventQueue to listen for
* passwords; if separate EventQueues are used for each ThreadGroup
* using AppContexts, the only key events that applet will be able to
* listen to are its own. A more reasonable applet request would be to
* change the Swing default look-and-feel; with that default stored in
* an AppContext, the applet's look-and-feel will change without
* disrupting other applets or potentially the browser itself.<p>
*
* Because the AppContext is a facility for safely extending application
* service support to applets, none of its methods may be blocked by a
* a SecurityManager check in a valid Java implementation. Applets may
* therefore safely invoke any of its methods without worry of being
* blocked.
*
* Note: If a SecurityManager is installed which derives from
* sun.awt.AWTSecurityManager, it may override the
* AWTSecurityManager.getAppContext() method to return the proper
* AppContext based on the execution context, in the case where
* the default ThreadGroup-based AppContext indexing would return
* the main "system" AppContext. For example, in an applet situation,
* if a system thread calls into an applet, rather than returning the
* main "system" AppContext (the one corresponding to the system thread),
* an installed AWTSecurityManager may return the applet's AppContext
* based on the execution context.
*
* @author Thomas Ball
* @author Fred Ecks
*/
public final class AppContext {
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.AppContext");
/* Since the contents of an AppContext are unique to each Java
* session, this class should never be serialized. */
/*
* The key to put()/get() the Java EventQueue into/from the AppContext.
*/
public static final Object EVENT_QUEUE_KEY = new StringBuffer("EventQueue");
/*
* The keys to store EventQueue push/pop lock and condition.
*/
public final static Object EVENT_QUEUE_LOCK_KEY = new StringBuilder("EventQueue.Lock");
public final static Object EVENT_QUEUE_COND_KEY = new StringBuilder("EventQueue.Condition");
/* A map of AppContexts, referenced by ThreadGroup.
*/
private static final Map<ThreadGroup, AppContext> threadGroup2appContext =
Collections.synchronizedMap(new IdentityHashMap<ThreadGroup, AppContext>());
/**
* Returns a set containing all <code>AppContext</code>s.
*/
public static Set<AppContext> getAppContexts() {
synchronized (threadGroup2appContext) {
return new HashSet<AppContext>(threadGroup2appContext.values());
}
}
/* The main "system" AppContext, used by everything not otherwise
contained in another AppContext. It is implicitly created for
standalone apps only (i.e. not applets)
*/
private static volatile AppContext mainAppContext = null;
private static class GetAppContextLock {};
private final static Object getAppContextLock = new GetAppContextLock();
/*
* The hash map associated with this AppContext. A private delegate
* is used instead of subclassing HashMap so as to avoid all of
* HashMap's potentially risky methods, such as clear(), elements(),
* putAll(), etc.
*/
private final Map<Object, Object> table = new HashMap<>();
private final ThreadGroup threadGroup;
/**
* If any <code>PropertyChangeListeners</code> have been registered,
* the <code>changeSupport</code> field describes them.
*
* @see #addPropertyChangeListener
* @see #removePropertyChangeListener
* @see #firePropertyChange
*/
private PropertyChangeSupport changeSupport = null;
public static final String DISPOSED_PROPERTY_NAME = "disposed";
public static final String GUI_DISPOSED = "guidisposed";
private enum State {
VALID,
BEING_DISPOSED,
DISPOSED
};
private volatile State state = State.VALID;
public boolean isDisposed() {
return state == State.DISPOSED;
}
/*
* The total number of AppContexts, system-wide. This number is
* incremented at the beginning of the constructor, and decremented
* at the end of dispose(). getAppContext() checks to see if this
* number is 1. If so, it returns the sole AppContext without
* checking Thread.currentThread().
*/
private static final AtomicInteger numAppContexts = new AtomicInteger(0);
/*
* The context ClassLoader that was used to create this AppContext.
*/
private final ClassLoader contextClassLoader;
/**
* Constructor for AppContext. This method is <i>not</i> public,
* nor should it ever be used as such. The proper way to construct
* an AppContext is through the use of SunToolkit.createNewAppContext.
* A ThreadGroup is created for the new AppContext, a Thread is
* created within that ThreadGroup, and that Thread calls
* SunToolkit.createNewAppContext before calling anything else.
* That creates both the new AppContext and its EventQueue.
*
* @param threadGroup The ThreadGroup for the new AppContext
* @see sun.awt.SunToolkit
* @since 1.2
*/
AppContext(ThreadGroup threadGroup) {
numAppContexts.incrementAndGet();
this.threadGroup = threadGroup;
threadGroup2appContext.put(threadGroup, this);
this.contextClassLoader =
AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
});
// Initialize push/pop lock and its condition to be used by all the
// EventQueues within this AppContext
Lock eventQueuePushPopLock = new ReentrantLock();
put(EVENT_QUEUE_LOCK_KEY, eventQueuePushPopLock);
Condition eventQueuePushPopCond = eventQueuePushPopLock.newCondition();
put(EVENT_QUEUE_COND_KEY, eventQueuePushPopCond);
}
private static final ThreadLocal<AppContext> threadAppContext =
new ThreadLocal<AppContext>();
private final static void initMainAppContext() {
// On the main Thread, we get the ThreadGroup, make a corresponding
// AppContext, and instantiate the Java EventQueue. This way, legacy
// code is unaffected by the move to multiple AppContext ability.
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
ThreadGroup currentThreadGroup =
Thread.currentThread().getThreadGroup();
ThreadGroup parentThreadGroup = currentThreadGroup.getParent();
while (parentThreadGroup != null) {
// Find the root ThreadGroup to construct our main AppContext
currentThreadGroup = parentThreadGroup;
parentThreadGroup = currentThreadGroup.getParent();
}
mainAppContext = SunToolkit.createNewAppContext(currentThreadGroup);
return null;
}
});
}
/**
* Returns the appropriate AppContext for the caller,
* as determined by its ThreadGroup. If the main "system" AppContext
* would be returned and there's an AWTSecurityManager installed, it
* is called to get the proper AppContext based on the execution
* context.
*
* @return the AppContext for the caller.
* @see java.lang.ThreadGroup
* @since 1.2
*/
public final static AppContext getAppContext() {
// we are standalone app, return the main app context
if (numAppContexts.get() == 1 && mainAppContext != null) {
return mainAppContext;
}
AppContext appContext = threadAppContext.get();
if (null == appContext) {
appContext = AccessController.doPrivileged(new PrivilegedAction<AppContext>()
{
public AppContext run() {
// Get the current ThreadGroup, and look for it and its
// parents in the hash from ThreadGroup to AppContext --
// it should be found, because we use createNewContext()
// when new AppContext objects are created.
ThreadGroup currentThreadGroup = Thread.currentThread().getThreadGroup();
ThreadGroup threadGroup = currentThreadGroup;
// Special case: we implicitly create the main app context
// if no contexts have been created yet. This covers standalone apps
// and excludes applets because by the time applet starts
// a number of contexts have already been created by the plugin.
synchronized (getAppContextLock) {
if (numAppContexts.get() == 0) {
if (System.getProperty("javaplugin.version") == null &&
System.getProperty("javawebstart.version") == null) {
initMainAppContext();
} else if (System.getProperty("javafx.version") != null &&
threadGroup.getParent() != null) {
// Swing inside JavaFX case
SunToolkit.createNewAppContext();
}
}
}
AppContext context = threadGroup2appContext.get(threadGroup);
while (context == null) {
threadGroup = threadGroup.getParent();
if (threadGroup == null) {
// We've got up to the root thread group and did not find an AppContext
// Try to get it from the security manager
SecurityManager securityManager = System.getSecurityManager();
if (securityManager != null) {
ThreadGroup smThreadGroup = securityManager.getThreadGroup();
if (smThreadGroup != null) {
/*
* If we get this far then it's likely that
* the ThreadGroup does not actually belong
* to the applet, so do not cache it.
*/
return threadGroup2appContext.get(smThreadGroup);
}
}
return null;
}
context = threadGroup2appContext.get(threadGroup);
}
// In case we did anything in the above while loop, we add
// all the intermediate ThreadGroups to threadGroup2appContext
// so we won't spin again.
for (ThreadGroup tg = currentThreadGroup; tg != threadGroup; tg = tg.getParent()) {
threadGroup2appContext.put(tg, context);
}
// Now we're done, so we cache the latest key/value pair.
threadAppContext.set(context);
return context;
}
});
}
return appContext;
}
/**
* Returns true if the specified AppContext is the main AppContext.
*
* @param ctx the context to compare with the main context
* @return true if the specified AppContext is the main AppContext.
* @since 1.8
*/
public final static boolean isMainContext(AppContext ctx) {
return (ctx != null && ctx == mainAppContext);
}
private final static AppContext getExecutionAppContext() {
SecurityManager securityManager = System.getSecurityManager();
if ((securityManager != null) &&
(securityManager instanceof AWTSecurityManager))
{
AWTSecurityManager awtSecMgr = (AWTSecurityManager) securityManager;
AppContext secAppContext = awtSecMgr.getAppContext();
return secAppContext; // Return what we're told
}
return null;
}
private long DISPOSAL_TIMEOUT = 5000; // Default to 5-second timeout
// for disposal of all Frames
// (we wait for this time twice,
// once for dispose(), and once
// to clear the EventQueue).
private long THREAD_INTERRUPT_TIMEOUT = 1000;
// Default to 1-second timeout for all
// interrupted Threads to exit, and another
// 1 second for all stopped Threads to die.
/**
* Disposes of this AppContext, all of its top-level Frames, and
* all Threads and ThreadGroups contained within it.
*
* This method must be called from a Thread which is not contained
* within this AppContext.
*
* @exception IllegalThreadStateException if the current thread is
* contained within this AppContext
* @since 1.2
*/
public void dispose() throws IllegalThreadStateException {
// Check to be sure that the current Thread isn't in this AppContext
if (this.threadGroup.parentOf(Thread.currentThread().getThreadGroup())) {
throw new IllegalThreadStateException(
"Current Thread is contained within AppContext to be disposed."
);
}
synchronized(this) {
if (this.state != State.VALID) {
return; // If already disposed or being disposed, bail.
}
this.state = State.BEING_DISPOSED;
}
final PropertyChangeSupport changeSupport = this.changeSupport;
if (changeSupport != null) {
changeSupport.firePropertyChange(DISPOSED_PROPERTY_NAME, false, true);
}
// First, we post an InvocationEvent to be run on the
// EventDispatchThread which disposes of all top-level Frames and TrayIcons
final Object notificationLock = new Object();
Runnable runnable = new Runnable() {
public void run() {
Window[] windowsToDispose = Window.getOwnerlessWindows();
for (Window w : windowsToDispose) {
try {
w.dispose();
} catch (Throwable t) {
log.finer("exception occurred while disposing app context", t);
}
}
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
if (!GraphicsEnvironment.isHeadless() && SystemTray.isSupported())
{
SystemTray systemTray = SystemTray.getSystemTray();
TrayIcon[] trayIconsToDispose = systemTray.getTrayIcons();
for (TrayIcon ti : trayIconsToDispose) {
systemTray.remove(ti);
}
}
return null;
}
});
// Alert PropertyChangeListeners that the GUI has been disposed.
if (changeSupport != null) {
changeSupport.firePropertyChange(GUI_DISPOSED, false, true);
}
synchronized(notificationLock) {
notificationLock.notifyAll(); // Notify caller that we're done
}
}
};
synchronized(notificationLock) {
SunToolkit.postEvent(this,
new InvocationEvent(Toolkit.getDefaultToolkit(), runnable));
try {
notificationLock.wait(DISPOSAL_TIMEOUT);
} catch (InterruptedException e) { }
}
// Next, we post another InvocationEvent to the end of the
// EventQueue. When it's executed, we know we've executed all
// events in the queue.
runnable = new Runnable() { public void run() {
synchronized(notificationLock) {
notificationLock.notifyAll(); // Notify caller that we're done
}
} };
synchronized(notificationLock) {
SunToolkit.postEvent(this,
new InvocationEvent(Toolkit.getDefaultToolkit(), runnable));
try {
notificationLock.wait(DISPOSAL_TIMEOUT);
} catch (InterruptedException e) { }
}
// We are done with posting events, so change the state to disposed
synchronized(this) {
this.state = State.DISPOSED;
}
// Next, we interrupt all Threads in the ThreadGroup
this.threadGroup.interrupt();
// Note, the EventDispatchThread we've interrupted may dump an
// InterruptedException to the console here. This needs to be
// fixed in the EventDispatchThread, not here.
// Next, we sleep 10ms at a time, waiting for all of the active
// Threads in the ThreadGroup to exit.
long startTime = System.currentTimeMillis();
long endTime = startTime + THREAD_INTERRUPT_TIMEOUT;
while ((this.threadGroup.activeCount() > 0) &&
(System.currentTimeMillis() < endTime)) {
try {
Thread.sleep(10);
} catch (InterruptedException e) { }
}
// Then, we stop any remaining Threads
this.threadGroup.stop();
// Next, we sleep 10ms at a time, waiting for all of the active
// Threads in the ThreadGroup to die.
startTime = System.currentTimeMillis();
endTime = startTime + THREAD_INTERRUPT_TIMEOUT;
while ((this.threadGroup.activeCount() > 0) &&
(System.currentTimeMillis() < endTime)) {
try {
Thread.sleep(10);
} catch (InterruptedException e) { }
}
// Next, we remove this and all subThreadGroups from threadGroup2appContext
int numSubGroups = this.threadGroup.activeGroupCount();
if (numSubGroups > 0) {
ThreadGroup [] subGroups = new ThreadGroup[numSubGroups];
numSubGroups = this.threadGroup.enumerate(subGroups);
for (int subGroup = 0; subGroup < numSubGroups; subGroup++) {
threadGroup2appContext.remove(subGroups[subGroup]);
}
}
threadGroup2appContext.remove(this.threadGroup);
threadAppContext.set(null);
// Finally, we destroy the ThreadGroup entirely.
try {
this.threadGroup.destroy();
} catch (IllegalThreadStateException e) {
// Fired if not all the Threads died, ignore it and proceed
}
synchronized (table) {
this.table.clear(); // Clear out the Hashtable to ease garbage collection
}
numAppContexts.decrementAndGet();
mostRecentKeyValue = null;
}
static final class PostShutdownEventRunnable implements Runnable {
private final AppContext appContext;
public PostShutdownEventRunnable(AppContext ac) {
appContext = ac;
}
public void run() {
final EventQueue eq = (EventQueue)appContext.get(EVENT_QUEUE_KEY);
if (eq != null) {
eq.postEvent(AWTAutoShutdown.getShutdownEvent());
}
}
}
static final class CreateThreadAction implements PrivilegedAction<Thread> {
private final AppContext appContext;
private final Runnable runnable;
public CreateThreadAction(AppContext ac, Runnable r) {
appContext = ac;
runnable = r;
}
public Thread run() {
Thread t = new Thread(appContext.getThreadGroup(), runnable);
t.setContextClassLoader(appContext.getContextClassLoader());
t.setPriority(Thread.NORM_PRIORITY + 1);
t.setDaemon(true);
return t;
}
}
static void stopEventDispatchThreads() {
for (AppContext appContext: getAppContexts()) {
if (appContext.isDisposed()) {
continue;
}
Runnable r = new PostShutdownEventRunnable(appContext);
// For security reasons EventQueue.postEvent should only be called
// on a thread that belongs to the corresponding thread group.
if (appContext != AppContext.getAppContext()) {
// Create a thread that belongs to the thread group associated
// with the AppContext and invokes EventQueue.postEvent.
PrivilegedAction<Thread> action = new CreateThreadAction(appContext, r);
Thread thread = AccessController.doPrivileged(action);
thread.start();
} else {
r.run();
}
}
}
private MostRecentKeyValue mostRecentKeyValue = null;
private MostRecentKeyValue shadowMostRecentKeyValue = null;
/**
* Returns the value to which the specified key is mapped in this context.
*
* @param key a key in the AppContext.
* @return the value to which the key is mapped in this AppContext;
* <code>null</code> if the key is not mapped to any value.
* @see #put(Object, Object)
* @since 1.2
*/
public Object get(Object key) {
/*
* The most recent reference should be updated inside a synchronized
* block to avoid a race when put() and get() are executed in
* parallel on different threads.
*/
synchronized (table) {
// Note: this most recent key/value caching is thread-hot.
// A simple test using SwingSet found that 72% of lookups
// were matched using the most recent key/value. By instantiating
// a simple MostRecentKeyValue object on cache misses, the
// cache hits can be processed without synchronization.
MostRecentKeyValue recent = mostRecentKeyValue;
if ((recent != null) && (recent.key == key)) {
return recent.value;
}
Object value = table.get(key);
if(mostRecentKeyValue == null) {
mostRecentKeyValue = new MostRecentKeyValue(key, value);
shadowMostRecentKeyValue = new MostRecentKeyValue(key, value);
} else {
MostRecentKeyValue auxKeyValue = mostRecentKeyValue;
shadowMostRecentKeyValue.setPair(key, value);
mostRecentKeyValue = shadowMostRecentKeyValue;
shadowMostRecentKeyValue = auxKeyValue;
}
return value;
}
}
/**
* Maps the specified <code>key</code> to the specified
* <code>value</code> in this AppContext. Neither the key nor the
* value can be <code>null</code>.
* <p>
* The value can be retrieved by calling the <code>get</code> method
* with a key that is equal to the original key.
*
* @param key the AppContext key.
* @param value the value.
* @return the previous value of the specified key in this
* AppContext, or <code>null</code> if it did not have one.
* @exception NullPointerException if the key or value is
* <code>null</code>.
* @see #get(Object)
* @since 1.2
*/
public Object put(Object key, Object value) {
synchronized (table) {
MostRecentKeyValue recent = mostRecentKeyValue;
if ((recent != null) && (recent.key == key))
recent.value = value;
return table.put(key, value);
}
}
/**
* Removes the key (and its corresponding value) from this
* AppContext. This method does nothing if the key is not in the
* AppContext.
*
* @param key the key that needs to be removed.
* @return the value to which the key had been mapped in this AppContext,
* or <code>null</code> if the key did not have a mapping.
* @since 1.2
*/
public Object remove(Object key) {
synchronized (table) {
MostRecentKeyValue recent = mostRecentKeyValue;
if ((recent != null) && (recent.key == key))
recent.value = null;
return table.remove(key);
}
}
/**
* Returns the root ThreadGroup for all Threads contained within
* this AppContext.
* @since 1.2
*/
public ThreadGroup getThreadGroup() {
return threadGroup;
}
/**
* Returns the context ClassLoader that was used to create this
* AppContext.
*
* @see java.lang.Thread#getContextClassLoader
*/
public ClassLoader getContextClassLoader() {
return contextClassLoader;
}
/**
* Returns a string representation of this AppContext.
* @since 1.2
*/
@Override
public String toString() {
return getClass().getName() + "[threadGroup=" + threadGroup.getName() + "]";
}
/**
* Returns an array of all the property change listeners
* registered on this component.
*
* @return all of this component's <code>PropertyChangeListener</code>s
* or an empty array if no property change
* listeners are currently registered
*
* @see #addPropertyChangeListener
* @see #removePropertyChangeListener
* @see #getPropertyChangeListeners(java.lang.String)
* @see java.beans.PropertyChangeSupport#getPropertyChangeListeners
* @since 1.4
*/
public synchronized PropertyChangeListener[] getPropertyChangeListeners() {
if (changeSupport == null) {
return new PropertyChangeListener[0];
}
return changeSupport.getPropertyChangeListeners();
}
/**
* Adds a PropertyChangeListener to the listener list for a specific
* property. The specified property may be one of the following:
* <ul>
* <li>if this AppContext is disposed ("disposed")</li>
* </ul>
* <ul>
* <li>if this AppContext's unowned Windows have been disposed
* ("guidisposed"). Code to cleanup after the GUI is disposed
* (such as LookAndFeel.uninitialize()) should execute in response to
* this property being fired. Notifications for the "guidisposed"
* property are sent on the event dispatch thread.</li>
* </ul>
* <p>
* If listener is null, no exception is thrown and no action is performed.
*
* @param propertyName one of the property names listed above
* @param listener the PropertyChangeListener to be added
*
* @see #removePropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener)
* @see #getPropertyChangeListeners(java.lang.String)
* @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener)
*/
public synchronized void addPropertyChangeListener(
String propertyName,
PropertyChangeListener listener) {
if (listener == null) {
return;
}
if (changeSupport == null) {
changeSupport = new PropertyChangeSupport(this);
}
changeSupport.addPropertyChangeListener(propertyName, listener);
}
/**
* Removes a PropertyChangeListener from the listener list for a specific
* property. This method should be used to remove PropertyChangeListeners
* that were registered for a specific bound property.
* <p>
* If listener is null, no exception is thrown and no action is performed.
*
* @param propertyName a valid property name
* @param listener the PropertyChangeListener to be removed
*
* @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener)
* @see #getPropertyChangeListeners(java.lang.String)
* @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
*/
public synchronized void removePropertyChangeListener(
String propertyName,
PropertyChangeListener listener) {
if (listener == null || changeSupport == null) {
return;
}
changeSupport.removePropertyChangeListener(propertyName, listener);
}
/**
* Returns an array of all the listeners which have been associated
* with the named property.
*
* @return all of the <code>PropertyChangeListeners</code> associated with
* the named property or an empty array if no listeners have
* been added
*
* @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener)
* @see #removePropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener)
* @see #getPropertyChangeListeners
* @since 1.4
*/
public synchronized PropertyChangeListener[] getPropertyChangeListeners(
String propertyName) {
if (changeSupport == null) {
return new PropertyChangeListener[0];
}
return changeSupport.getPropertyChangeListeners(propertyName);
}
// Set up JavaAWTAccess in SharedSecrets
static {
sun.misc.SharedSecrets.setJavaAWTAccess(new sun.misc.JavaAWTAccess() {
private boolean hasRootThreadGroup(final AppContext ecx) {
return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ecx.threadGroup.getParent() == null;
}
});
}
/**
* Returns the AppContext used for applet logging isolation, or null if
* the default global context can be used.
* If there's no applet, or if the caller is a stand alone application,
* or running in the main app context, returns null.
* Otherwise, returns the AppContext of the calling applet.
* @return null if the global default context can be used,
* an AppContext otherwise.
**/
public Object getAppletContext() {
// There's no AppContext: return null.
// No need to call getAppContext() if numAppContext == 0:
// it means that no AppContext has been created yet, and
// we don't want to trigger the creation of a main app
// context since we don't need it.
if (numAppContexts.get() == 0) return null;
// Get the context from the security manager
AppContext ecx = getExecutionAppContext();
// Not sure we really need to re-check numAppContexts here.
// If all applets have gone away then we could have a
// numAppContexts coming back to 0. So we recheck
// it here because we don't want to trigger the
// creation of a main AppContext in that case.
// This is probably not 100% MT-safe but should reduce
// the window of opportunity in which that issue could
// happen.
if (numAppContexts.get() > 0) {
// Defaults to thread group caching.
// This is probably not required as we only really need
// isolation in a deployed applet environment, in which
// case ecx will not be null when we reach here
// However it helps emulate the deployed environment,
// in tests for instance.
ecx = ecx != null ? ecx : getAppContext();
}
// getAppletContext() may be called when initializing the main
// app context - in which case mainAppContext will still be
// null. To work around this issue we simply use
// AppContext.threadGroup.getParent() == null instead, since
// mainAppContext is the only AppContext which should have
// the root TG as its thread group.
// See: JDK-8023258
final boolean isMainAppContext = ecx == null
|| mainAppContext == ecx
|| mainAppContext == null && hasRootThreadGroup(ecx);
return isMainAppContext ? null : ecx;
}
});
}
public static <T> T getSoftReferenceValue(Object key,
Supplier<T> supplier) {
final AppContext appContext = AppContext.getAppContext();
SoftReference<T> ref = (SoftReference<T>) appContext.get(key);
if (ref != null) {
final T object = ref.get();
if (object != null) {
return object;
}
}
final T object = supplier.get();
ref = new SoftReference<>(object);
appContext.put(key, ref);
return object;
}
}
final class MostRecentKeyValue {
Object key;
Object value;
MostRecentKeyValue(Object k, Object v) {
key = k;
value = v;
}
void setPair(Object k, Object v) {
key = k;
value = v;
}
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright (c) 2003, 2011, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.event.FocusEvent;
import java.awt.Component;
/**
* This class represents FocusEvents with a known "cause" - reason why this event happened. It can
* be mouse press, traversal, activation, and so on - all causes are described as Cause enum. The
* event with the cause can be constructed in two ways - explicitly through constructor of
* CausedFocusEvent class or implicitly, by calling appropriate requestFocusXXX method with "cause"
* parameter. The default cause is UNKNOWN.
*/
@SuppressWarnings("serial")
public class CausedFocusEvent extends FocusEvent {
public enum Cause {
UNKNOWN,
MOUSE_EVENT,
TRAVERSAL,
TRAVERSAL_UP,
TRAVERSAL_DOWN,
TRAVERSAL_FORWARD,
TRAVERSAL_BACKWARD,
MANUAL_REQUEST,
AUTOMATIC_TRAVERSE,
ROLLBACK,
NATIVE_SYSTEM,
ACTIVATION,
CLEAR_GLOBAL_FOCUS_OWNER,
RETARGETED
};
private final Cause cause;
public Cause getCause() {
return cause;
}
public String toString() {
return "java.awt.FocusEvent[" + super.paramString() + ",cause=" + cause + "] on " + getSource();
}
public CausedFocusEvent(Component source, int id, boolean temporary,
Component opposite, Cause cause) {
super(source, id, temporary, opposite);
if (cause == null) {
cause = Cause.UNKNOWN;
}
this.cause = cause;
}
/**
* Retargets the original focus event to the new target. If the
* original focus event is CausedFocusEvent, it remains such and
* cause is copied. Otherwise, new CausedFocusEvent is created,
* with cause as RETARGETED.
* @return retargeted event, or null if e is null
*/
public static FocusEvent retarget(FocusEvent e, Component newSource) {
if (e == null) return null;
return new CausedFocusEvent(newSource, e.getID(), e.isTemporary(), e.getOppositeComponent(),
(e instanceof CausedFocusEvent) ? ((CausedFocusEvent)e).getCause() : Cause.RETARGETED);
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 1996, 2012, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
public class CharsetString {
/**
* chars for this string. See also offset, length.
*/
public char[] charsetChars;
/**
* Offset within charsetChars of first character
**/
public int offset;
/**
* Length of the string we represent.
**/
public int length;
/**
* This string's FontDescriptor.
*/
public FontDescriptor fontDescriptor;
/**
* Creates a new CharsetString
*/
public CharsetString(char charsetChars[], int offset, int length,
FontDescriptor fontDescriptor){
this.charsetChars = charsetChars;
this.offset = offset;
this.length = length;
this.fontDescriptor = fontDescriptor;
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (c) 2000, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import sun.awt.datatransfer.DataTransferer;
import java.awt.*;
import java.awt.dnd.*;
import java.awt.dnd.peer.DragSourceContextPeer;
import java.awt.peer.*;
/**
* Interface for component creation support in toolkits
*/
public interface ComponentFactory {
CanvasPeer createCanvas(Canvas target) throws HeadlessException;
PanelPeer createPanel(Panel target) throws HeadlessException;
WindowPeer createWindow(Window target) throws HeadlessException;
FramePeer createFrame(Frame target) throws HeadlessException;
DialogPeer createDialog(Dialog target) throws HeadlessException;
ButtonPeer createButton(Button target) throws HeadlessException;
TextFieldPeer createTextField(TextField target)
throws HeadlessException;
ChoicePeer createChoice(Choice target) throws HeadlessException;
LabelPeer createLabel(Label target) throws HeadlessException;
ListPeer createList(List target) throws HeadlessException;
CheckboxPeer createCheckbox(Checkbox target)
throws HeadlessException;
ScrollbarPeer createScrollbar(Scrollbar target)
throws HeadlessException;
ScrollPanePeer createScrollPane(ScrollPane target)
throws HeadlessException;
TextAreaPeer createTextArea(TextArea target)
throws HeadlessException;
FileDialogPeer createFileDialog(FileDialog target)
throws HeadlessException;
MenuBarPeer createMenuBar(MenuBar target) throws HeadlessException;
MenuPeer createMenu(Menu target) throws HeadlessException;
PopupMenuPeer createPopupMenu(PopupMenu target)
throws HeadlessException;
MenuItemPeer createMenuItem(MenuItem target)
throws HeadlessException;
CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target)
throws HeadlessException;
DragSourceContextPeer createDragSourceContextPeer(
DragGestureEvent dge)
throws InvalidDnDOperationException, HeadlessException;
FontPeer getFontPeer(String name, int style);
RobotPeer createRobot(Robot target, GraphicsDevice screen)
throws AWTException, HeadlessException;
DataTransferer getDataTransferer();
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 1998, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
/**
* This interface can be implemented on a Graphics object to allow
* the lightweight component code to permanently install a rectangular
* maximum clip that cannot be extended with setClip and which works in
* conjunction with the hit() and getTransform() methods of Graphics2D
* to make it appear as if there really was a component with these
* dimensions.
*/
public interface ConstrainableGraphics {
/**
* Constrain this graphics object to have a permanent device space
* origin of (x, y) and a permanent maximum clip of (x,y,w,h).
* Calling this method is roughly equivalent to:
* g.translate(x, y);
* g.clipRect(0, 0, w, h);
* except that the clip can never be extended outside of these
* bounds, even with setClip() and for the fact that the (x,y)
* become a new device space coordinate origin.
*
* These methods are recursive so that you can further restrict
* the object by calling the constrain() method more times, but
* you can never enlarge its restricted maximum clip.
*/
public void constrain(int x, int y, int w, int h);
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright (c) 1997, 1999, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.*;
import java.awt.image.*;
/**
* A class to encapsulate a custom image-based cursor.
*
* @author ThomasBall
*/
public abstract class CustomCursor extends Cursor {
protected Image image;
public CustomCursor(Image cursor, Point hotSpot, String name)
throws IndexOutOfBoundsException {
super(name);
image = cursor;
Toolkit toolkit = Toolkit.getDefaultToolkit();
// Make sure image is fully loaded.
Component c = new Canvas(); // for its imageUpdate method
MediaTracker tracker = new MediaTracker(c);
tracker.addImage(cursor, 0);
try {
tracker.waitForAll();
} catch (InterruptedException e) {
}
int width = cursor.getWidth(c);
int height = cursor.getHeight(c);
// Fix for bug 4212593 The Toolkit.createCustomCursor does not
// check absence of the image of cursor
// If the image is invalid, the cursor will be hidden (made completely
// transparent). In this case, getBestCursorSize() will adjust negative w and h,
// but we need to set the hotspot inside the image here.
if (tracker.isErrorAny() || width < 0 || height < 0) {
hotSpot.x = hotSpot.y = 0;
}
// Scale image to nearest supported size.
Dimension nativeSize = toolkit.getBestCursorSize(width, height);
if ((nativeSize.width != width || nativeSize.height != height) &&
(nativeSize.width != 0 && nativeSize.height != 0)) {
cursor = cursor.getScaledInstance(nativeSize.width,
nativeSize.height,
Image.SCALE_DEFAULT);
width = nativeSize.width;
height = nativeSize.height;
}
// Verify that the hotspot is within cursor bounds.
if (hotSpot.x >= width || hotSpot.y >= height || hotSpot.x < 0 || hotSpot.y < 0) {
throw new IndexOutOfBoundsException("invalid hotSpot");
}
/* Extract ARGB array from image.
*
* A transparency mask can be created in native code by checking
* each pixel's top byte -- a 0 value means the pixel's transparent.
* Since each platform's format of the bitmap and mask are likely to
* be different, their creation shouldn't be here.
*/
int[] pixels = new int[width * height];
ImageProducer ip = cursor.getSource();
PixelGrabber pg = new PixelGrabber(ip, 0, 0, width, height,
pixels, 0, width);
try {
pg.grabPixels();
} catch (InterruptedException e) {
}
createNativeCursor(image, pixels, width, height, hotSpot.x, hotSpot.y);
}
protected abstract void createNativeCursor(Image im, int[] pixels,
int width, int height,
int xHotSpot, int yHotSpot);
}

View File

@@ -0,0 +1,311 @@
/*
* Copyright (c) 1999, 2013, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.io.*;
import java.util.*;
import sun.util.logging.PlatformLogger;
/*
* Internal class that manages sun.awt.Debug settings.
* Settings can be specified on a global, per-package,
* or per-class level.
*
* Properties affecting the behaviour of the Debug class are
* loaded from the awtdebug.properties file at class load
* time. The properties file is assumed to be in the
* user.home directory. A different file can be used
* by setting the awtdebug.properties system property.
* e.g. java -Dawtdebug.properties=foo.properties
*
* Only properties beginning with 'awtdebug' have any
* meaning-- all other properties are ignored.
*
* You can override the properties file by specifying
* 'awtdebug' props as system properties on the command line.
* e.g. java -Dawtdebug.trace=true
* Properties specific to a package or a class can be set
* by qualifying the property names as follows:
* awtdebug.<property name>.<class or package name>
* So for example, turning on tracing in the com.acme.Fubar
* class would be done as follows:
* awtdebug.trace.com.acme.Fubar=true
*
* Class settings always override package settings, which in
* turn override global settings.
*
* Addition from July, 2007.
*
* After the fix for 4638447 all the usage of DebugHelper
* classes in Java code are replaced with the corresponding
* Java Logging API calls. This file is now used only to
* control native logging.
*
* To enable native logging you should set the following
* system property to 'true': sun.awt.nativedebug. After
* the native logging is enabled, the actual debug settings
* are read the same way as described above (as before
* the fix for 4638447).
*/
final class DebugSettings {
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.debug.DebugSettings");
/* standard debug property key names */
static final String PREFIX = "awtdebug";
static final String PROP_FILE = "properties";
/* default property settings */
private static final String DEFAULT_PROPS[] = {
"awtdebug.assert=true",
"awtdebug.trace=false",
"awtdebug.on=true",
"awtdebug.ctrace=false"
};
/* global instance of the settings object */
private static DebugSettings instance = null;
private Properties props = new Properties();
static void init() {
if (instance != null) {
return;
}
NativeLibLoader.loadLibraries();
instance = new DebugSettings();
instance.loadNativeSettings();
}
private DebugSettings() {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
public Void run() {
loadProperties();
return null;
}
});
}
/*
* Load debug properties from file, then override
* with any command line specified properties
*/
private synchronized void loadProperties() {
// setup initial properties
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
public Void run() {
loadDefaultProperties();
loadFileProperties();
loadSystemProperties();
return null;
}
});
// echo the initial property settings to stdout
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("DebugSettings:\n{0}", this);
}
}
public String toString() {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
PrintStream pout = new PrintStream(bout);
for (String key : props.stringPropertyNames()) {
String value = props.getProperty(key, "");
pout.println(key + " = " + value);
}
return new String(bout.toByteArray());
}
/*
* Sets up default property values
*/
private void loadDefaultProperties() {
// is there a more inefficient way to setup default properties?
// maybe, but this has got to be close to 100% non-optimal
try {
for ( int nprop = 0; nprop < DEFAULT_PROPS.length; nprop++ ) {
StringBufferInputStream in = new StringBufferInputStream(DEFAULT_PROPS[nprop]);
props.load(in);
in.close();
}
} catch(IOException ioe) {
}
}
/*
* load properties from file, overriding defaults
*/
private void loadFileProperties() {
String propPath;
Properties fileProps;
// check if the user specified a particular settings file
propPath = System.getProperty(PREFIX + "." + PROP_FILE, "");
if (propPath.equals("")) {
// otherwise get it from the user's home directory
propPath = System.getProperty("user.home", "") +
File.separator +
PREFIX + "." + PROP_FILE;
}
File propFile = new File(propPath);
try {
println("Reading debug settings from '" + propFile.getCanonicalPath() + "'...");
FileInputStream fin = new FileInputStream(propFile);
props.load(fin);
fin.close();
} catch ( FileNotFoundException fne ) {
println("Did not find settings file.");
} catch ( IOException ioe ) {
println("Problem reading settings, IOException: " + ioe.getMessage());
}
}
/*
* load properties from system props (command line spec'd usually),
* overriding default or file properties
*/
private void loadSystemProperties() {
// override file properties with system properties
Properties sysProps = System.getProperties();
for (String key : sysProps.stringPropertyNames()) {
String value = sysProps.getProperty(key,"");
// copy any "awtdebug" properties over
if ( key.startsWith(PREFIX) ) {
props.setProperty(key, value);
}
}
}
/**
* Gets named boolean property
* @param key Name of property
* @param defval Default value if property does not exist
* @return boolean value of the named property
*/
public synchronized boolean getBoolean(String key, boolean defval) {
String value = getString(key, String.valueOf(defval));
return value.equalsIgnoreCase("true");
}
/**
* Gets named integer property
* @param key Name of property
* @param defval Default value if property does not exist
* @return integer value of the named property
*/
public synchronized int getInt(String key, int defval) {
String value = getString(key, String.valueOf(defval));
return Integer.parseInt(value);
}
/**
* Gets named String property
* @param key Name of property
* @param defval Default value if property does not exist
* @return string value of the named property
*/
public synchronized String getString(String key, String defval) {
String actualKeyName = PREFIX + "." + key;
String value = props.getProperty(actualKeyName, defval);
//println(actualKeyName+"="+value);
return value;
}
private synchronized List<String> getPropertyNames() {
List<String> propNames = new LinkedList<>();
// remove global prefix from property names
for (String propName : props.stringPropertyNames()) {
propName = propName.substring(PREFIX.length()+1);
propNames.add(propName);
}
return propNames;
}
private void println(Object object) {
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer(object.toString());
}
}
private static final String PROP_CTRACE = "ctrace";
private static final int PROP_CTRACE_LEN = PROP_CTRACE.length();
private native synchronized void setCTracingOn(boolean enabled);
private native synchronized void setCTracingOn(boolean enabled, String file);
private native synchronized void setCTracingOn(boolean enabled, String file, int line);
private void loadNativeSettings() {
boolean ctracingOn;
ctracingOn = getBoolean(PROP_CTRACE, false);
setCTracingOn(ctracingOn);
//
// Filter out file/line ctrace properties from debug settings
//
List<String> traces = new LinkedList<>();
for (String key : getPropertyNames()) {
if (key.startsWith(PROP_CTRACE) && key.length() > PROP_CTRACE_LEN) {
traces.add(key);
}
}
// sort traces list so file-level traces will be before line-level ones
Collections.sort(traces);
//
// Setup the trace points
//
for (String key : traces) {
String trace = key.substring(PROP_CTRACE_LEN+1);
String filespec;
String linespec;
int delim= trace.indexOf('@');
boolean enabled;
// parse out the filename and linenumber from the property name
filespec = delim != -1 ? trace.substring(0, delim) : trace;
linespec = delim != -1 ? trace.substring(delim+1) : "";
enabled = getBoolean(key, false);
//System.out.println("Key="+key+", File="+filespec+", Line="+linespec+", Enabled="+enabled);
if ( linespec.length() == 0 ) {
// set file specific trace setting
setCTracingOn(enabled, filespec);
} else {
// set line specific trace setting
int linenum = Integer.parseInt(linespec, 10);
setCTracingOn(enabled, filespec, linenum);
}
}
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2003, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.Point;
import java.awt.Window;
import java.awt.peer.MouseInfoPeer;
public class DefaultMouseInfoPeer implements MouseInfoPeer {
/**
* Package-private constructor to prevent instantiation.
*/
DefaultMouseInfoPeer() {
}
public native int fillPointWithCoords(Point point);
public native boolean isWindowUnderMouse(Window w);
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2006, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.net.URL;
public abstract class DesktopBrowse {
private static volatile DesktopBrowse mInstance;
public static void setInstance(DesktopBrowse instance) {
if (mInstance != null) {
throw new IllegalStateException("DesktopBrowse instance has already been set.");
}
mInstance = instance;
}
public static DesktopBrowse getInstance() {
return mInstance;
}
public abstract void browse(URL url);
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 2000, 2001, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.util.EventListener;
/**
* The listener interface for receiving display change events.
* The class that is interested in processing a display change event
* implements this interface (and all the methods it
* contains).
*
* For Motif, this interface is only used for dragging windows between Xinerama
* screens.
*
* For win32, the listener object created from that class is then registered
* with the WToolkit object using its <code>addDisplayChangeListener</code>
* method. When the display resolution is changed (which occurs,
* in Windows, either by the user changing the properties of the
* display through the control panel or other utility or by
* some other application which has gotten fullscreen-exclusive
* control of the display), the listener is notified through its
* displayChanged() or paletteChanged() methods.
*
* @author Chet Haase
* @author Brent Christian
* @since 1.4
*/
public interface DisplayChangedListener extends EventListener {
/**
* Invoked when the display mode has changed.
*/
public void displayChanged();
/**
* Invoked when the palette has changed.
*/
public void paletteChanged();
}

View File

@@ -0,0 +1,586 @@
/*
* Copyright (c) 1996, 2015, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.awt.peer.*;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import java.util.Set;
import java.awt.AWTKeyStroke;
import java.applet.Applet;
import sun.applet.AppletPanel;
/**
* A generic container used for embedding Java components, usually applets.
* An EmbeddedFrame has two related uses:
*
* . Within a Java-based application, an EmbeddedFrame serves as a sort of
* firewall, preventing the contained components or applets from using
* getParent() to find parent components, such as menubars.
*
* . Within a C-based application, an EmbeddedFrame contains a window handle
* which was created by the application, which serves as the top-level
* Java window. EmbeddedFrames created for this purpose are passed-in a
* handle of an existing window created by the application. The window
* handle should be of the appropriate native type for a specific
* platform, as stored in the pData field of the ComponentPeer.
*
* @author Thomas Ball
*/
public abstract class EmbeddedFrame extends Frame
implements KeyEventDispatcher, PropertyChangeListener {
private boolean isCursorAllowed = true;
private boolean supportsXEmbed = false;
private KeyboardFocusManager appletKFM;
// JDK 1.1 compatibility
private static final long serialVersionUID = 2967042741780317130L;
/*
* The constants define focus traversal directions.
* Use them in {@code traverseIn}, {@code traverseOut} methods.
*/
protected static final boolean FORWARD = true;
protected static final boolean BACKWARD = false;
public boolean supportsXEmbed() {
return supportsXEmbed && SunToolkit.needsXEmbed();
}
protected EmbeddedFrame(boolean supportsXEmbed) {
this((long)0, supportsXEmbed);
}
protected EmbeddedFrame() {
this((long)0);
}
/**
* @deprecated This constructor will be removed in 1.5
*/
@Deprecated
protected EmbeddedFrame(int handle) {
this((long)handle);
}
protected EmbeddedFrame(long handle) {
this(handle, false);
}
protected EmbeddedFrame(long handle, boolean supportsXEmbed) {
this.supportsXEmbed = supportsXEmbed;
registerListeners();
}
/**
* Block introspection of a parent window by this child.
*/
public Container getParent() {
return null;
}
/**
* Needed to track which KeyboardFocusManager is current. We want to avoid memory
* leaks, so when KFM stops being current, we remove ourselves as listeners.
*/
public void propertyChange(PropertyChangeEvent evt) {
// We don't handle any other properties. Skip it.
if (!evt.getPropertyName().equals("managingFocus")) {
return;
}
// We only do it if it stops being current. Technically, we should
// never get an event about KFM starting being current.
if (evt.getNewValue() == Boolean.TRUE) {
return;
}
// should be the same as appletKFM
removeTraversingOutListeners((KeyboardFocusManager)evt.getSource());
appletKFM = KeyboardFocusManager.getCurrentKeyboardFocusManager();
if (isVisible()) {
addTraversingOutListeners(appletKFM);
}
}
/**
* Register us as KeyEventDispatcher and property "managingFocus" listeners.
*/
private void addTraversingOutListeners(KeyboardFocusManager kfm) {
kfm.addKeyEventDispatcher(this);
kfm.addPropertyChangeListener("managingFocus", this);
}
/**
* Deregister us as KeyEventDispatcher and property "managingFocus" listeners.
*/
private void removeTraversingOutListeners(KeyboardFocusManager kfm) {
kfm.removeKeyEventDispatcher(this);
kfm.removePropertyChangeListener("managingFocus", this);
}
/**
* Because there may be many AppContexts, and we can't be sure where this
* EmbeddedFrame is first created or shown, we can't automatically determine
* the correct KeyboardFocusManager to attach to as KeyEventDispatcher.
* Those who want to use the functionality of traversing out of the EmbeddedFrame
* must call this method on the Applet's AppContext. After that, all the changes
* can be handled automatically, including possible replacement of
* KeyboardFocusManager.
*/
public void registerListeners() {
if (appletKFM != null) {
removeTraversingOutListeners(appletKFM);
}
appletKFM = KeyboardFocusManager.getCurrentKeyboardFocusManager();
if (isVisible()) {
addTraversingOutListeners(appletKFM);
}
}
/**
* Needed to avoid memory leak: we register this EmbeddedFrame as a listener with
* KeyboardFocusManager of applet's AppContext. We don't want the KFM to keep
* reference to our EmbeddedFrame forever if the Frame is no longer in use, so we
* add listeners in show() and remove them in hide().
*/
@SuppressWarnings("deprecation")
public void show() {
if (appletKFM != null) {
addTraversingOutListeners(appletKFM);
}
super.show();
}
/**
* Needed to avoid memory leak: we register this EmbeddedFrame as a listener with
* KeyboardFocusManager of applet's AppContext. We don't want the KFM to keep
* reference to our EmbeddedFrame forever if the Frame is no longer in use, so we
* add listeners in show() and remove them in hide().
*/
@SuppressWarnings("deprecation")
public void hide() {
if (appletKFM != null) {
removeTraversingOutListeners(appletKFM);
}
super.hide();
}
/**
* Need this method to detect when the focus may have chance to leave the
* focus cycle root which is EmbeddedFrame. Mostly, the code here is copied
* from DefaultKeyboardFocusManager.processKeyEvent with some minor
* modifications.
*/
public boolean dispatchKeyEvent(KeyEvent e) {
Container currentRoot = AWTAccessor.getKeyboardFocusManagerAccessor()
.getCurrentFocusCycleRoot();
// if we are not in EmbeddedFrame's cycle, we should not try to leave.
if (this != currentRoot) {
return false;
}
// KEY_TYPED events cannot be focus traversal keys
if (e.getID() == KeyEvent.KEY_TYPED) {
return false;
}
if (!getFocusTraversalKeysEnabled() || e.isConsumed()) {
return false;
}
AWTKeyStroke stroke = AWTKeyStroke.getAWTKeyStrokeForEvent(e);
Set<AWTKeyStroke> toTest;
Component currentFocused = e.getComponent();
toTest = getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
if (toTest.contains(stroke)) {
// 6581899: performance improvement for SortingFocusTraversalPolicy
Component last = getFocusTraversalPolicy().getLastComponent(this);
if (currentFocused == last || last == null) {
if (traverseOut(FORWARD)) {
e.consume();
return true;
}
}
}
toTest = getFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
if (toTest.contains(stroke)) {
// 6581899: performance improvement for SortingFocusTraversalPolicy
Component first = getFocusTraversalPolicy().getFirstComponent(this);
if (currentFocused == first || first == null) {
if (traverseOut(BACKWARD)) {
e.consume();
return true;
}
}
}
return false;
}
/**
* This method is called by the embedder when we should receive focus as element
* of the traversal chain. The method requests focus on:
* 1. the first Component of this EmbeddedFrame if user moves focus forward
* in the focus traversal cycle.
* 2. the last Component of this EmbeddedFrame if user moves focus backward
* in the focus traversal cycle.
*
* The direction parameter specifies which of the two mentioned cases is
* happening. Use FORWARD and BACKWARD constants defined in the EmbeddedFrame class
* to avoid confusing boolean values.
*
* A concrete implementation of this method is defined in the platform-dependent
* subclasses.
*
* @param direction FORWARD or BACKWARD
* @return true, if the EmbeddedFrame wants to get focus, false otherwise.
*/
public boolean traverseIn(boolean direction) {
Component comp = null;
if (direction == FORWARD) {
comp = getFocusTraversalPolicy().getFirstComponent(this);
} else {
comp = getFocusTraversalPolicy().getLastComponent(this);
}
if (comp != null) {
// comp.requestFocus(); - Leads to a hung.
AWTAccessor.getKeyboardFocusManagerAccessor().setMostRecentFocusOwner(this, comp);
synthesizeWindowActivation(true);
}
return (null != comp);
}
/**
* This method is called from dispatchKeyEvent in the following two cases:
* 1. The focus is on the first Component of this EmbeddedFrame and we are
* about to transfer the focus backward.
* 2. The focus in on the last Component of this EmbeddedFrame and we are
* about to transfer the focus forward.
* This is needed to give the opportuity for keyboard focus to leave the
* EmbeddedFrame. Override this method, initiate focus transfer in it and
* return true if you want the focus to leave EmbeddedFrame's cycle.
* The direction parameter specifies which of the two mentioned cases is
* happening. Use FORWARD and BACKWARD constants defined in EmbeddedFrame
* to avoid confusing boolean values.
*
* @param direction FORWARD or BACKWARD
* @return true, if EmbeddedFrame wants the focus to leave it,
* false otherwise.
*/
protected boolean traverseOut(boolean direction) {
return false;
}
/**
* Block modifying any frame attributes, since they aren't applicable
* for EmbeddedFrames.
*/
public void setTitle(String title) {}
public void setIconImage(Image image) {}
public void setIconImages(java.util.List<? extends Image> icons) {}
public void setMenuBar(MenuBar mb) {}
public void setResizable(boolean resizable) {}
public void remove(MenuComponent m) {}
public boolean isResizable() {
return true;
}
@SuppressWarnings("deprecation")
public void addNotify() {
synchronized (getTreeLock()) {
if (getPeer() == null) {
setPeer(new NullEmbeddedFramePeer());
}
super.addNotify();
}
}
// These three functions consitute RFE 4100710. Do not remove.
@SuppressWarnings("deprecation")
public void setCursorAllowed(boolean isCursorAllowed) {
this.isCursorAllowed = isCursorAllowed;
getPeer().updateCursorImmediately();
}
public boolean isCursorAllowed() {
return isCursorAllowed;
}
public Cursor getCursor() {
return (isCursorAllowed)
? super.getCursor()
: Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
}
@SuppressWarnings("deprecation")
protected void setPeer(final ComponentPeer p){
AWTAccessor.getComponentAccessor().setPeer(EmbeddedFrame.this, p);
};
/**
* Synthesize native message to activate or deactivate EmbeddedFrame window
* depending on the value of parameter <code>b</code>.
* Peers should override this method if they are to implement
* this functionality.
* @param doActivate if <code>true</code>, activates the window;
* otherwise, deactivates the window
*/
public void synthesizeWindowActivation(boolean doActivate) {}
/**
* Moves this embedded frame to a new location. The top-left corner of
* the new location is specified by the <code>x</code> and <code>y</code>
* parameters relative to the native parent component.
* <p>
* setLocation() and setBounds() for EmbeddedFrame really don't move it
* within the native parent. These methods always put embedded frame to
* (0, 0) for backward compatibility. To allow moving embedded frame
* setLocationPrivate() and setBoundsPrivate() were introduced, and they
* work just the same way as setLocation() and setBounds() for usual,
* non-embedded components.
* </p>
* <p>
* Using usual get/setLocation() and get/setBounds() together with new
* get/setLocationPrivate() and get/setBoundsPrivate() is not recommended.
* For example, calling getBoundsPrivate() after setLocation() works fine,
* but getBounds() after setBoundsPrivate() may return unpredictable value.
* </p>
* @param x the new <i>x</i>-coordinate relative to the parent component
* @param y the new <i>y</i>-coordinate relative to the parent component
* @see java.awt.Component#setLocation
* @see #getLocationPrivate
* @see #setBoundsPrivate
* @see #getBoundsPrivate
* @since 1.5
*/
protected void setLocationPrivate(int x, int y) {
Dimension size = getSize();
setBoundsPrivate(x, y, size.width, size.height);
}
/**
* Gets the location of this embedded frame as a point specifying the
* top-left corner relative to parent component.
* <p>
* setLocation() and setBounds() for EmbeddedFrame really don't move it
* within the native parent. These methods always put embedded frame to
* (0, 0) for backward compatibility. To allow getting location and size
* of embedded frame getLocationPrivate() and getBoundsPrivate() were
* introduced, and they work just the same way as getLocation() and getBounds()
* for ususal, non-embedded components.
* </p>
* <p>
* Using usual get/setLocation() and get/setBounds() together with new
* get/setLocationPrivate() and get/setBoundsPrivate() is not recommended.
* For example, calling getBoundsPrivate() after setLocation() works fine,
* but getBounds() after setBoundsPrivate() may return unpredictable value.
* </p>
* @return a point indicating this embedded frame's top-left corner
* @see java.awt.Component#getLocation
* @see #setLocationPrivate
* @see #setBoundsPrivate
* @see #getBoundsPrivate
* @since 1.6
*/
protected Point getLocationPrivate() {
Rectangle bounds = getBoundsPrivate();
return new Point(bounds.x, bounds.y);
}
/**
* Moves and resizes this embedded frame. The new location of the top-left
* corner is specified by <code>x</code> and <code>y</code> parameters
* relative to the native parent component. The new size is specified by
* <code>width</code> and <code>height</code>.
* <p>
* setLocation() and setBounds() for EmbeddedFrame really don't move it
* within the native parent. These methods always put embedded frame to
* (0, 0) for backward compatibility. To allow moving embedded frames
* setLocationPrivate() and setBoundsPrivate() were introduced, and they
* work just the same way as setLocation() and setBounds() for usual,
* non-embedded components.
* </p>
* <p>
* Using usual get/setLocation() and get/setBounds() together with new
* get/setLocationPrivate() and get/setBoundsPrivate() is not recommended.
* For example, calling getBoundsPrivate() after setLocation() works fine,
* but getBounds() after setBoundsPrivate() may return unpredictable value.
* </p>
* @param x the new <i>x</i>-coordinate relative to the parent component
* @param y the new <i>y</i>-coordinate relative to the parent component
* @param width the new <code>width</code> of this embedded frame
* @param height the new <code>height</code> of this embedded frame
* @see java.awt.Component#setBounds
* @see #setLocationPrivate
* @see #getLocationPrivate
* @see #getBoundsPrivate
* @since 1.5
*/
@SuppressWarnings("deprecation")
protected void setBoundsPrivate(int x, int y, int width, int height) {
final FramePeer peer = (FramePeer)getPeer();
if (peer != null) {
peer.setBoundsPrivate(x, y, width, height);
}
}
/**
* Gets the bounds of this embedded frame as a rectangle specifying the
* width, height and location relative to the native parent component.
* <p>
* setLocation() and setBounds() for EmbeddedFrame really don't move it
* within the native parent. These methods always put embedded frame to
* (0, 0) for backward compatibility. To allow getting location and size
* of embedded frames getLocationPrivate() and getBoundsPrivate() were
* introduced, and they work just the same way as getLocation() and getBounds()
* for ususal, non-embedded components.
* </p>
* <p>
* Using usual get/setLocation() and get/setBounds() together with new
* get/setLocationPrivate() and get/setBoundsPrivate() is not recommended.
* For example, calling getBoundsPrivate() after setLocation() works fine,
* but getBounds() after setBoundsPrivate() may return unpredictable value.
* </p>
* @return a rectangle indicating this embedded frame's bounds
* @see java.awt.Component#getBounds
* @see #setLocationPrivate
* @see #getLocationPrivate
* @see #setBoundsPrivate
* @since 1.6
*/
@SuppressWarnings("deprecation")
protected Rectangle getBoundsPrivate() {
final FramePeer peer = (FramePeer)getPeer();
if (peer != null) {
return peer.getBoundsPrivate();
}
else {
return getBounds();
}
}
public void toFront() {}
public void toBack() {}
public abstract void registerAccelerator(AWTKeyStroke stroke);
public abstract void unregisterAccelerator(AWTKeyStroke stroke);
/**
* Checks if the component is in an EmbeddedFrame. If so,
* returns the applet found in the hierarchy or null if
* not found.
* @return the parent applet or {@ null}
* @since 1.6
*/
public static Applet getAppletIfAncestorOf(Component comp) {
Container parent = comp.getParent();
Applet applet = null;
while (parent != null && !(parent instanceof EmbeddedFrame)) {
if (parent instanceof Applet) {
applet = (Applet)parent;
}
parent = parent.getParent();
}
return parent == null ? null : applet;
}
/**
* This method should be overriden in subclasses. It is
* called when window this frame is within should be blocked
* by some modal dialog.
*/
public void notifyModalBlocked(Dialog blocker, boolean blocked) {
}
private static class NullEmbeddedFramePeer
extends NullComponentPeer implements FramePeer {
public void setTitle(String title) {}
public void setIconImage(Image im) {}
public void updateIconImages() {}
public void setMenuBar(MenuBar mb) {}
public void setResizable(boolean resizeable) {}
public void setState(int state) {}
public int getState() { return Frame.NORMAL; }
public void setMaximizedBounds(Rectangle b) {}
public void toFront() {}
public void toBack() {}
public void updateFocusableWindowState() {}
public void updateAlwaysOnTop() {}
public void updateAlwaysOnTopState() {}
public Component getGlobalHeavyweightFocusOwner() { return null; }
public void setBoundsPrivate(int x, int y, int width, int height) {
setBounds(x, y, width, height, SET_BOUNDS);
}
public Rectangle getBoundsPrivate() {
return getBounds();
}
public void setModalBlocked(Dialog blocker, boolean blocked) {}
/**
* @see java.awt.peer.ContainerPeer#restack
*/
public void restack() {
throw new UnsupportedOperationException();
}
/**
* @see java.awt.peer.ContainerPeer#isRestackSupported
*/
public boolean isRestackSupported() {
return false;
}
public boolean requestWindowFocus() {
return false;
}
public void updateMinimumSize() {
}
public void setOpacity(float opacity) {
}
public void setOpaque(boolean isOpaque) {
}
public void updateWindow() {
}
public void repositionSecurityWarning() {
}
public void emulateActivation(boolean activate) {
}
}
} // class EmbeddedFrame

View File

@@ -0,0 +1,175 @@
/*
* Copyright (c) 2003, 2011, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.lang.reflect.Array;
import java.util.EventListener;
/**
* A class that assists in managing {@link java.util.EventListener}s of
* the specified type. Its instance holds an array of listeners of the same
* type and allows to perform the typical operations on the listeners.
* This class is thread-safe.
*
* @author Alexander Gerasimov
*
* @since 1.5
*/
public class EventListenerAggregate {
private EventListener[] listenerList;
/**
* Constructs an <code>EventListenerAggregate</code> object.
*
* @param listenerClass the type of the listeners to be managed by this object
*
* @throws NullPointerException if <code>listenerClass</code> is
* <code>null</code>
* @throws ClassCastException if <code>listenerClass</code> is not
* assignable to <code>java.util.EventListener</code>
*/
public EventListenerAggregate(Class<? extends EventListener> listenerClass) {
if (listenerClass == null) {
throw new NullPointerException("listener class is null");
}
listenerList = (EventListener[])Array.newInstance(listenerClass, 0);
}
private Class<?> getListenerClass() {
return listenerList.getClass().getComponentType();
}
/**
* Adds the listener to this aggregate.
*
* @param listener the listener to be added
*
* @throws ClassCastException if <code>listener</code> is not
* an instatce of <code>listenerClass</code> specified
* in the constructor
*/
public synchronized void add(EventListener listener) {
Class<?> listenerClass = getListenerClass();
if (!listenerClass.isInstance(listener)) { // null is not an instance of any class
throw new ClassCastException("listener " + listener + " is not " +
"an instance of listener class " + listenerClass);
}
EventListener[] tmp = (EventListener[])Array.newInstance(listenerClass, listenerList.length + 1);
System.arraycopy(listenerList, 0, tmp, 0, listenerList.length);
tmp[listenerList.length] = listener;
listenerList = tmp;
}
/**
* Removes a listener that is equal to the given one from this aggregate.
* <code>equals()</code> method is used to compare listeners.
*
* @param listener the listener to be removed
*
* @return <code>true</code> if this aggregate contained the specified
* <code>listener</code>; <code>false</code> otherwise
*
* @throws ClassCastException if <code>listener</code> is not
* an instatce of <code>listenerClass</code> specified
* in the constructor
*/
public synchronized boolean remove(EventListener listener) {
Class<?> listenerClass = getListenerClass();
if (!listenerClass.isInstance(listener)) { // null is not an instance of any class
throw new ClassCastException("listener " + listener + " is not " +
"an instance of listener class " + listenerClass);
}
for (int i = 0; i < listenerList.length; i++) {
if (listenerList[i].equals(listener)) {
EventListener[] tmp = (EventListener[])Array.newInstance(listenerClass,
listenerList.length - 1);
System.arraycopy(listenerList, 0, tmp, 0, i);
System.arraycopy(listenerList, i + 1, tmp, i, listenerList.length - i - 1);
listenerList = tmp;
return true;
}
}
return false;
}
/**
* Returns an array of all the listeners contained in this aggregate.
* The array is the data structure in which listeners are stored internally.
* The runtime type of the returned array is "array of <code>listenerClass</code>"
* (<code>listenerClass</code> has been specified as a parameter to
* the constructor of this class).
*
* @return all the listeners contained in this aggregate (an empty
* array if there are no listeners)
*/
public synchronized EventListener[] getListenersInternal() {
return listenerList;
}
/**
* Returns an array of all the listeners contained in this aggregate.
* The array is a copy of the data structure in which listeners are stored
* internally.
* The runtime type of the returned array is "array of <code>listenerClass</code>"
* (<code>listenerClass</code> has been specified as a parameter to
* the constructor of this class).
*
* @return a copy of all the listeners contained in this aggregate (an empty
* array if there are no listeners)
*/
public synchronized EventListener[] getListenersCopy() {
return (listenerList.length == 0) ? listenerList : listenerList.clone();
}
/**
* Returns the number of lisetners in this aggregate.
*
* @return the number of lisetners in this aggregate
*/
public synchronized int size() {
return listenerList.length;
}
/**
* Returns <code>true</code> if this aggregate contains no listeners,
* <code>false</code> otherwise.
*
* @return <code>true</code> if this aggregate contains no listeners,
* <code>false</code> otherwise
*/
public synchronized boolean isEmpty() {
return listenerList.length == 0;
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (c) 2008, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.AWTEvent;
import java.awt.EventQueue;
public class EventQueueDelegate {
private static final Object EVENT_QUEUE_DELEGATE_KEY =
new StringBuilder("EventQueueDelegate.Delegate");
public static void setDelegate(Delegate delegate) {
AppContext.getAppContext().put(EVENT_QUEUE_DELEGATE_KEY, delegate);
}
public static Delegate getDelegate() {
return
(Delegate) AppContext.getAppContext().get(EVENT_QUEUE_DELEGATE_KEY);
}
public interface Delegate {
/**
* This method allows for changing {@code EventQueue} events order.
*
* @param eventQueue current {@code EventQueue}
* @return next {@code event} for the {@code EventDispatchThread}
*/
public AWTEvent getNextEvent(EventQueue eventQueue) throws InterruptedException;
/**
* Notifies delegate before EventQueue.dispatch method.
*
* Note: this method may mutate the event
*
* @param event to be dispatched by {@code dispatch} method
* @return handle to be passed to {@code afterDispatch} method
*/
public Object beforeDispatch(AWTEvent event) throws InterruptedException;
/**
* Notifies delegate after EventQueue.dispatch method.
*
* @param event {@code event} dispatched by the {@code dispatch} method
* @param handle object which came from {@code beforeDispatch} method
*/
public void afterDispatch(AWTEvent event, Object handle) throws InterruptedException;
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (c) 2008, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.AWTEvent;
public class EventQueueItem {
public AWTEvent event;
public EventQueueItem next;
public EventQueueItem(AWTEvent evt) {
event = evt;
}
}

View File

@@ -0,0 +1,669 @@
/*
* Copyright (c) 2009, 2018, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.awt.event.KeyEvent;
public class ExtendedKeyCodes {
/**
* ATTN: These are the readonly hashes with load factor == 1;
* adding a value, please set the inital capacity to exact number of items
* or higher.
*/
// Keycodes declared in KeyEvent.java with corresponding Unicode values.
private final static HashMap<Integer, Integer> regularKeyCodesMap =
new HashMap<Integer,Integer>(98, 1.0f);
// Keycodes derived from Unicode values. Here should be collected codes
// for characters appearing on the primary layer of at least one
// known keyboard layout. For instance, sterling sign is on the primary layer
// of the Mac Italian layout.
private final static HashSet<Integer> extendedKeyCodesSet =
new HashSet<Integer>(501, 1.0f);
final public static int getExtendedKeyCodeForChar( int c ) {
int uc = Character.toUpperCase( c );
int lc = Character.toLowerCase( c );
if (regularKeyCodesMap.containsKey( c )) {
if(regularKeyCodesMap.containsKey(uc)) {
return regularKeyCodesMap.get( uc );
}
return regularKeyCodesMap.get( c );
}
uc += 0x01000000;
lc += 0x01000000;
if (extendedKeyCodesSet.contains( uc )) {
return uc;
}else if (extendedKeyCodesSet.contains( lc )) {
return lc;
}
return KeyEvent.VK_UNDEFINED;
}
static {
regularKeyCodesMap.put(0x08, KeyEvent.VK_BACK_SPACE);
regularKeyCodesMap.put(0x09, KeyEvent.VK_TAB);
regularKeyCodesMap.put(0x0a, KeyEvent.VK_ENTER);
regularKeyCodesMap.put(0x1B, KeyEvent.VK_ESCAPE);
regularKeyCodesMap.put(0x20AC, KeyEvent.VK_EURO_SIGN);
regularKeyCodesMap.put(0x20, KeyEvent.VK_SPACE);
regularKeyCodesMap.put(0x21, KeyEvent.VK_EXCLAMATION_MARK);
regularKeyCodesMap.put(0x22, KeyEvent.VK_QUOTEDBL);
regularKeyCodesMap.put(0x23, KeyEvent.VK_NUMBER_SIGN);
regularKeyCodesMap.put(0x24, KeyEvent.VK_DOLLAR);
regularKeyCodesMap.put(0x26, KeyEvent.VK_AMPERSAND);
regularKeyCodesMap.put(0x27, KeyEvent.VK_QUOTE);
regularKeyCodesMap.put(0x28, KeyEvent.VK_LEFT_PARENTHESIS);
regularKeyCodesMap.put(0x29, KeyEvent.VK_RIGHT_PARENTHESIS);
regularKeyCodesMap.put(0x2A, KeyEvent.VK_ASTERISK);
regularKeyCodesMap.put(0x2B, KeyEvent.VK_PLUS);
regularKeyCodesMap.put(0x2C, KeyEvent.VK_COMMA);
regularKeyCodesMap.put(0x2D, KeyEvent.VK_MINUS);
regularKeyCodesMap.put(0x2E, KeyEvent.VK_PERIOD);
regularKeyCodesMap.put(0x2F, KeyEvent.VK_SLASH);
regularKeyCodesMap.put(0x30, KeyEvent.VK_0);
regularKeyCodesMap.put(0x31, KeyEvent.VK_1);
regularKeyCodesMap.put(0x32, KeyEvent.VK_2);
regularKeyCodesMap.put(0x33, KeyEvent.VK_3);
regularKeyCodesMap.put(0x34, KeyEvent.VK_4);
regularKeyCodesMap.put(0x35, KeyEvent.VK_5);
regularKeyCodesMap.put(0x36, KeyEvent.VK_6);
regularKeyCodesMap.put(0x37, KeyEvent.VK_7);
regularKeyCodesMap.put(0x38, KeyEvent.VK_8);
regularKeyCodesMap.put(0x39, KeyEvent.VK_9);
regularKeyCodesMap.put(0x3A, KeyEvent.VK_COLON);
regularKeyCodesMap.put(0x3B, KeyEvent.VK_SEMICOLON);
regularKeyCodesMap.put(0x3C, KeyEvent.VK_LESS);
regularKeyCodesMap.put(0x3D, KeyEvent.VK_EQUALS);
regularKeyCodesMap.put(0x3E, KeyEvent.VK_GREATER);
regularKeyCodesMap.put(0x40, KeyEvent.VK_AT);
regularKeyCodesMap.put(0x41, KeyEvent.VK_A);
regularKeyCodesMap.put(0x42, KeyEvent.VK_B);
regularKeyCodesMap.put(0x43, KeyEvent.VK_C);
regularKeyCodesMap.put(0x44, KeyEvent.VK_D);
regularKeyCodesMap.put(0x45, KeyEvent.VK_E);
regularKeyCodesMap.put(0x46, KeyEvent.VK_F);
regularKeyCodesMap.put(0x47, KeyEvent.VK_G);
regularKeyCodesMap.put(0x48, KeyEvent.VK_H);
regularKeyCodesMap.put(0x49, KeyEvent.VK_I);
regularKeyCodesMap.put(0x4A, KeyEvent.VK_J);
regularKeyCodesMap.put(0x4B, KeyEvent.VK_K);
regularKeyCodesMap.put(0x4C, KeyEvent.VK_L);
regularKeyCodesMap.put(0x4D, KeyEvent.VK_M);
regularKeyCodesMap.put(0x4E, KeyEvent.VK_N);
regularKeyCodesMap.put(0x4F, KeyEvent.VK_O);
regularKeyCodesMap.put(0x50, KeyEvent.VK_P);
regularKeyCodesMap.put(0x51, KeyEvent.VK_Q);
regularKeyCodesMap.put(0x52, KeyEvent.VK_R);
regularKeyCodesMap.put(0x53, KeyEvent.VK_S);
regularKeyCodesMap.put(0x54, KeyEvent.VK_T);
regularKeyCodesMap.put(0x55, KeyEvent.VK_U);
regularKeyCodesMap.put(0x56, KeyEvent.VK_V);
regularKeyCodesMap.put(0x57, KeyEvent.VK_W);
regularKeyCodesMap.put(0x58, KeyEvent.VK_X);
regularKeyCodesMap.put(0x59, KeyEvent.VK_Y);
regularKeyCodesMap.put(0x5A, KeyEvent.VK_Z);
regularKeyCodesMap.put(0x5B, KeyEvent.VK_OPEN_BRACKET);
regularKeyCodesMap.put(0x5C, KeyEvent.VK_BACK_SLASH);
regularKeyCodesMap.put(0x5D, KeyEvent.VK_CLOSE_BRACKET);
regularKeyCodesMap.put(0x5E, KeyEvent.VK_CIRCUMFLEX);
regularKeyCodesMap.put(0x5F, KeyEvent.VK_UNDERSCORE);
regularKeyCodesMap.put(0x60, KeyEvent.VK_BACK_QUOTE);
regularKeyCodesMap.put(0x61, KeyEvent.VK_A);
regularKeyCodesMap.put(0x62, KeyEvent.VK_B);
regularKeyCodesMap.put(0x63, KeyEvent.VK_C);
regularKeyCodesMap.put(0x64, KeyEvent.VK_D);
regularKeyCodesMap.put(0x65, KeyEvent.VK_E);
regularKeyCodesMap.put(0x66, KeyEvent.VK_F);
regularKeyCodesMap.put(0x67, KeyEvent.VK_G);
regularKeyCodesMap.put(0x68, KeyEvent.VK_H);
regularKeyCodesMap.put(0x69, KeyEvent.VK_I);
regularKeyCodesMap.put(0x6A, KeyEvent.VK_J);
regularKeyCodesMap.put(0x6B, KeyEvent.VK_K);
regularKeyCodesMap.put(0x6C, KeyEvent.VK_L);
regularKeyCodesMap.put(0x6D, KeyEvent.VK_M);
regularKeyCodesMap.put(0x6E, KeyEvent.VK_N);
regularKeyCodesMap.put(0x6F, KeyEvent.VK_O);
regularKeyCodesMap.put(0x70, KeyEvent.VK_P);
regularKeyCodesMap.put(0x71, KeyEvent.VK_Q);
regularKeyCodesMap.put(0x72, KeyEvent.VK_R);
regularKeyCodesMap.put(0x73, KeyEvent.VK_S);
regularKeyCodesMap.put(0x74, KeyEvent.VK_T);
regularKeyCodesMap.put(0x75, KeyEvent.VK_U);
regularKeyCodesMap.put(0x76, KeyEvent.VK_V);
regularKeyCodesMap.put(0x77, KeyEvent.VK_W);
regularKeyCodesMap.put(0x78, KeyEvent.VK_X);
regularKeyCodesMap.put(0x79, KeyEvent.VK_Y);
regularKeyCodesMap.put(0x7A, KeyEvent.VK_Z);
regularKeyCodesMap.put(0x7B, KeyEvent.VK_BRACELEFT);
regularKeyCodesMap.put(0x7D, KeyEvent.VK_BRACERIGHT);
regularKeyCodesMap.put(0x7F, KeyEvent.VK_DELETE);
regularKeyCodesMap.put(0xA1, KeyEvent.VK_INVERTED_EXCLAMATION_MARK);
extendedKeyCodesSet.add(0x01000000+0x0060);
extendedKeyCodesSet.add(0x01000000+0x007C);
extendedKeyCodesSet.add(0x01000000+0x007E);
extendedKeyCodesSet.add(0x01000000+0x00A2);
extendedKeyCodesSet.add(0x01000000+0x00A3);
extendedKeyCodesSet.add(0x01000000+0x00A5);
extendedKeyCodesSet.add(0x01000000+0x00A7);
extendedKeyCodesSet.add(0x01000000+0x00A8);
extendedKeyCodesSet.add(0x01000000+0x00AB);
extendedKeyCodesSet.add(0x01000000+0x00B0);
extendedKeyCodesSet.add(0x01000000+0x00B1);
extendedKeyCodesSet.add(0x01000000+0x00B2);
extendedKeyCodesSet.add(0x01000000+0x00B3);
extendedKeyCodesSet.add(0x01000000+0x00B4);
extendedKeyCodesSet.add(0x01000000+0x00B5);
extendedKeyCodesSet.add(0x01000000+0x00B6);
extendedKeyCodesSet.add(0x01000000+0x00B7);
extendedKeyCodesSet.add(0x01000000+0x00B9);
extendedKeyCodesSet.add(0x01000000+0x00BA);
extendedKeyCodesSet.add(0x01000000+0x00BB);
extendedKeyCodesSet.add(0x01000000+0x00BC);
extendedKeyCodesSet.add(0x01000000+0x00BD);
extendedKeyCodesSet.add(0x01000000+0x00BE);
extendedKeyCodesSet.add(0x01000000+0x00BF);
extendedKeyCodesSet.add(0x01000000+0x00C4);
extendedKeyCodesSet.add(0x01000000+0x00C5);
extendedKeyCodesSet.add(0x01000000+0x00C6);
extendedKeyCodesSet.add(0x01000000+0x00C7);
extendedKeyCodesSet.add(0x01000000+0x00D1);
extendedKeyCodesSet.add(0x01000000+0x00D6);
extendedKeyCodesSet.add(0x01000000+0x00D7);
extendedKeyCodesSet.add(0x01000000+0x00D8);
extendedKeyCodesSet.add(0x01000000+0x00DF);
extendedKeyCodesSet.add(0x01000000+0x00E0);
extendedKeyCodesSet.add(0x01000000+0x00E1);
extendedKeyCodesSet.add(0x01000000+0x00E2);
extendedKeyCodesSet.add(0x01000000+0x00E4);
extendedKeyCodesSet.add(0x01000000+0x00E5);
extendedKeyCodesSet.add(0x01000000+0x00E6);
extendedKeyCodesSet.add(0x01000000+0x00E7);
extendedKeyCodesSet.add(0x01000000+0x00E8);
extendedKeyCodesSet.add(0x01000000+0x00E9);
extendedKeyCodesSet.add(0x01000000+0x00EA);
extendedKeyCodesSet.add(0x01000000+0x00EB);
extendedKeyCodesSet.add(0x01000000+0x00EC);
extendedKeyCodesSet.add(0x01000000+0x00ED);
extendedKeyCodesSet.add(0x01000000+0x00EE);
extendedKeyCodesSet.add(0x01000000+0x00F0);
extendedKeyCodesSet.add(0x01000000+0x00F1);
extendedKeyCodesSet.add(0x01000000+0x00F2);
extendedKeyCodesSet.add(0x01000000+0x00F3);
extendedKeyCodesSet.add(0x01000000+0x00F4);
extendedKeyCodesSet.add(0x01000000+0x00F5);
extendedKeyCodesSet.add(0x01000000+0x00F6);
extendedKeyCodesSet.add(0x01000000+0x00F7);
extendedKeyCodesSet.add(0x01000000+0x00F8);
extendedKeyCodesSet.add(0x01000000+0x00F9);
extendedKeyCodesSet.add(0x01000000+0x00FA);
extendedKeyCodesSet.add(0x01000000+0x00FB);
extendedKeyCodesSet.add(0x01000000+0x00FC);
extendedKeyCodesSet.add(0x01000000+0x00FD);
extendedKeyCodesSet.add(0x01000000+0x00FE);
extendedKeyCodesSet.add(0x01000000+0x0105);
extendedKeyCodesSet.add(0x01000000+0x02DB);
extendedKeyCodesSet.add(0x01000000+0x0142);
extendedKeyCodesSet.add(0x01000000+0x013E);
extendedKeyCodesSet.add(0x01000000+0x015B);
extendedKeyCodesSet.add(0x01000000+0x0161);
extendedKeyCodesSet.add(0x01000000+0x015F);
extendedKeyCodesSet.add(0x01000000+0x0165);
extendedKeyCodesSet.add(0x01000000+0x017E);
extendedKeyCodesSet.add(0x01000000+0x017C);
extendedKeyCodesSet.add(0x01000000+0x0103);
extendedKeyCodesSet.add(0x01000000+0x0107);
extendedKeyCodesSet.add(0x01000000+0x010D);
extendedKeyCodesSet.add(0x01000000+0x0119);
extendedKeyCodesSet.add(0x01000000+0x011B);
extendedKeyCodesSet.add(0x01000000+0x0111);
extendedKeyCodesSet.add(0x01000000+0x0148);
extendedKeyCodesSet.add(0x01000000+0x0151);
extendedKeyCodesSet.add(0x01000000+0x0171);
extendedKeyCodesSet.add(0x01000000+0x0159);
extendedKeyCodesSet.add(0x01000000+0x016F);
extendedKeyCodesSet.add(0x01000000+0x0163);
extendedKeyCodesSet.add(0x01000000+0x02D9);
extendedKeyCodesSet.add(0x01000000+0x0130);
extendedKeyCodesSet.add(0x01000000+0x0127);
extendedKeyCodesSet.add(0x01000000+0x0125);
extendedKeyCodesSet.add(0x01000000+0x0131);
extendedKeyCodesSet.add(0x01000000+0x011F);
extendedKeyCodesSet.add(0x01000000+0x0135);
extendedKeyCodesSet.add(0x01000000+0x010B);
extendedKeyCodesSet.add(0x01000000+0x0109);
extendedKeyCodesSet.add(0x01000000+0x0121);
extendedKeyCodesSet.add(0x01000000+0x011D);
extendedKeyCodesSet.add(0x01000000+0x016D);
extendedKeyCodesSet.add(0x01000000+0x015D);
extendedKeyCodesSet.add(0x01000000+0x0138);
extendedKeyCodesSet.add(0x01000000+0x0157);
extendedKeyCodesSet.add(0x01000000+0x013C);
extendedKeyCodesSet.add(0x01000000+0x0113);
extendedKeyCodesSet.add(0x01000000+0x0123);
extendedKeyCodesSet.add(0x01000000+0x0167);
extendedKeyCodesSet.add(0x01000000+0x014B);
extendedKeyCodesSet.add(0x01000000+0x0101);
extendedKeyCodesSet.add(0x01000000+0x012F);
extendedKeyCodesSet.add(0x01000000+0x0117);
extendedKeyCodesSet.add(0x01000000+0x012B);
extendedKeyCodesSet.add(0x01000000+0x0146);
extendedKeyCodesSet.add(0x01000000+0x014D);
extendedKeyCodesSet.add(0x01000000+0x0137);
extendedKeyCodesSet.add(0x01000000+0x0173);
extendedKeyCodesSet.add(0x01000000+0x016B);
extendedKeyCodesSet.add(0x01000000+0x0153);
extendedKeyCodesSet.add(0x01000000+0x30FC);
extendedKeyCodesSet.add(0x01000000+0x30A2);
extendedKeyCodesSet.add(0x01000000+0x30A4);
extendedKeyCodesSet.add(0x01000000+0x30A6);
extendedKeyCodesSet.add(0x01000000+0x30A8);
extendedKeyCodesSet.add(0x01000000+0x30AA);
extendedKeyCodesSet.add(0x01000000+0x30AB);
extendedKeyCodesSet.add(0x01000000+0x30AD);
extendedKeyCodesSet.add(0x01000000+0x30AF);
extendedKeyCodesSet.add(0x01000000+0x30B1);
extendedKeyCodesSet.add(0x01000000+0x30B3);
extendedKeyCodesSet.add(0x01000000+0x30B5);
extendedKeyCodesSet.add(0x01000000+0x30B7);
extendedKeyCodesSet.add(0x01000000+0x30B9);
extendedKeyCodesSet.add(0x01000000+0x30BB);
extendedKeyCodesSet.add(0x01000000+0x30BD);
extendedKeyCodesSet.add(0x01000000+0x30BF);
extendedKeyCodesSet.add(0x01000000+0x30C1);
extendedKeyCodesSet.add(0x01000000+0x30C4);
extendedKeyCodesSet.add(0x01000000+0x30C6);
extendedKeyCodesSet.add(0x01000000+0x30C8);
extendedKeyCodesSet.add(0x01000000+0x30CA);
extendedKeyCodesSet.add(0x01000000+0x30CB);
extendedKeyCodesSet.add(0x01000000+0x30CC);
extendedKeyCodesSet.add(0x01000000+0x30CD);
extendedKeyCodesSet.add(0x01000000+0x30CE);
extendedKeyCodesSet.add(0x01000000+0x30CF);
extendedKeyCodesSet.add(0x01000000+0x30D2);
extendedKeyCodesSet.add(0x01000000+0x30D5);
extendedKeyCodesSet.add(0x01000000+0x30D8);
extendedKeyCodesSet.add(0x01000000+0x30DB);
extendedKeyCodesSet.add(0x01000000+0x30DE);
extendedKeyCodesSet.add(0x01000000+0x30DF);
extendedKeyCodesSet.add(0x01000000+0x30E0);
extendedKeyCodesSet.add(0x01000000+0x30E1);
extendedKeyCodesSet.add(0x01000000+0x30E2);
extendedKeyCodesSet.add(0x01000000+0x30E4);
extendedKeyCodesSet.add(0x01000000+0x30E6);
extendedKeyCodesSet.add(0x01000000+0x30E8);
extendedKeyCodesSet.add(0x01000000+0x30E9);
extendedKeyCodesSet.add(0x01000000+0x30EA);
extendedKeyCodesSet.add(0x01000000+0x30EB);
extendedKeyCodesSet.add(0x01000000+0x30EC);
extendedKeyCodesSet.add(0x01000000+0x30ED);
extendedKeyCodesSet.add(0x01000000+0x30EF);
extendedKeyCodesSet.add(0x01000000+0x30F3);
extendedKeyCodesSet.add(0x01000000+0x309B);
extendedKeyCodesSet.add(0x01000000+0x309C);
extendedKeyCodesSet.add(0x01000000+0x06F0);
extendedKeyCodesSet.add(0x01000000+0x06F1);
extendedKeyCodesSet.add(0x01000000+0x06F2);
extendedKeyCodesSet.add(0x01000000+0x06F3);
extendedKeyCodesSet.add(0x01000000+0x06F4);
extendedKeyCodesSet.add(0x01000000+0x06F5);
extendedKeyCodesSet.add(0x01000000+0x06F6);
extendedKeyCodesSet.add(0x01000000+0x06F7);
extendedKeyCodesSet.add(0x01000000+0x06F8);
extendedKeyCodesSet.add(0x01000000+0x06F9);
extendedKeyCodesSet.add(0x01000000+0x0670);
extendedKeyCodesSet.add(0x01000000+0x067E);
extendedKeyCodesSet.add(0x01000000+0x0686);
extendedKeyCodesSet.add(0x01000000+0x060C);
extendedKeyCodesSet.add(0x01000000+0x06D4);
extendedKeyCodesSet.add(0x01000000+0x0660);
extendedKeyCodesSet.add(0x01000000+0x0661);
extendedKeyCodesSet.add(0x01000000+0x0662);
extendedKeyCodesSet.add(0x01000000+0x0663);
extendedKeyCodesSet.add(0x01000000+0x0664);
extendedKeyCodesSet.add(0x01000000+0x0665);
extendedKeyCodesSet.add(0x01000000+0x0666);
extendedKeyCodesSet.add(0x01000000+0x0667);
extendedKeyCodesSet.add(0x01000000+0x0668);
extendedKeyCodesSet.add(0x01000000+0x0669);
extendedKeyCodesSet.add(0x01000000+0x061B);
extendedKeyCodesSet.add(0x01000000+0x0621);
extendedKeyCodesSet.add(0x01000000+0x0624);
extendedKeyCodesSet.add(0x01000000+0x0626);
extendedKeyCodesSet.add(0x01000000+0x0627);
extendedKeyCodesSet.add(0x01000000+0x0628);
extendedKeyCodesSet.add(0x01000000+0x0629);
extendedKeyCodesSet.add(0x01000000+0x062A);
extendedKeyCodesSet.add(0x01000000+0x062B);
extendedKeyCodesSet.add(0x01000000+0x062C);
extendedKeyCodesSet.add(0x01000000+0x062D);
extendedKeyCodesSet.add(0x01000000+0x062E);
extendedKeyCodesSet.add(0x01000000+0x062F);
extendedKeyCodesSet.add(0x01000000+0x0630);
extendedKeyCodesSet.add(0x01000000+0x0631);
extendedKeyCodesSet.add(0x01000000+0x0632);
extendedKeyCodesSet.add(0x01000000+0x0633);
extendedKeyCodesSet.add(0x01000000+0x0634);
extendedKeyCodesSet.add(0x01000000+0x0635);
extendedKeyCodesSet.add(0x01000000+0x0636);
extendedKeyCodesSet.add(0x01000000+0x0637);
extendedKeyCodesSet.add(0x01000000+0x0638);
extendedKeyCodesSet.add(0x01000000+0x0639);
extendedKeyCodesSet.add(0x01000000+0x063A);
extendedKeyCodesSet.add(0x01000000+0x0641);
extendedKeyCodesSet.add(0x01000000+0x0642);
extendedKeyCodesSet.add(0x01000000+0x0643);
extendedKeyCodesSet.add(0x01000000+0x0644);
extendedKeyCodesSet.add(0x01000000+0x0645);
extendedKeyCodesSet.add(0x01000000+0x0646);
extendedKeyCodesSet.add(0x01000000+0x0647);
extendedKeyCodesSet.add(0x01000000+0x0648);
extendedKeyCodesSet.add(0x01000000+0x0649);
extendedKeyCodesSet.add(0x01000000+0x064A);
extendedKeyCodesSet.add(0x01000000+0x064E);
extendedKeyCodesSet.add(0x01000000+0x064F);
extendedKeyCodesSet.add(0x01000000+0x0650);
extendedKeyCodesSet.add(0x01000000+0x0652);
extendedKeyCodesSet.add(0x01000000+0x0698);
extendedKeyCodesSet.add(0x01000000+0x06A4);
extendedKeyCodesSet.add(0x01000000+0x06A9);
extendedKeyCodesSet.add(0x01000000+0x06AF);
extendedKeyCodesSet.add(0x01000000+0x06BE);
extendedKeyCodesSet.add(0x01000000+0x06CC);
extendedKeyCodesSet.add(0x01000000+0x06CC);
extendedKeyCodesSet.add(0x01000000+0x06D2);
extendedKeyCodesSet.add(0x01000000+0x0493);
extendedKeyCodesSet.add(0x01000000+0x0497);
extendedKeyCodesSet.add(0x01000000+0x049B);
extendedKeyCodesSet.add(0x01000000+0x049D);
extendedKeyCodesSet.add(0x01000000+0x04A3);
extendedKeyCodesSet.add(0x01000000+0x04AF);
extendedKeyCodesSet.add(0x01000000+0x04B1);
extendedKeyCodesSet.add(0x01000000+0x04B3);
extendedKeyCodesSet.add(0x01000000+0x04B9);
extendedKeyCodesSet.add(0x01000000+0x04BB);
extendedKeyCodesSet.add(0x01000000+0x04D9);
extendedKeyCodesSet.add(0x01000000+0x04E9);
extendedKeyCodesSet.add(0x01000000+0x0452);
extendedKeyCodesSet.add(0x01000000+0x0453);
extendedKeyCodesSet.add(0x01000000+0x0451);
extendedKeyCodesSet.add(0x01000000+0x0454);
extendedKeyCodesSet.add(0x01000000+0x0455);
extendedKeyCodesSet.add(0x01000000+0x0456);
extendedKeyCodesSet.add(0x01000000+0x0457);
extendedKeyCodesSet.add(0x01000000+0x0458);
extendedKeyCodesSet.add(0x01000000+0x0459);
extendedKeyCodesSet.add(0x01000000+0x045A);
extendedKeyCodesSet.add(0x01000000+0x045B);
extendedKeyCodesSet.add(0x01000000+0x045C);
extendedKeyCodesSet.add(0x01000000+0x0491);
extendedKeyCodesSet.add(0x01000000+0x045E);
extendedKeyCodesSet.add(0x01000000+0x045F);
extendedKeyCodesSet.add(0x01000000+0x2116);
extendedKeyCodesSet.add(0x01000000+0x044E);
extendedKeyCodesSet.add(0x01000000+0x0430);
extendedKeyCodesSet.add(0x01000000+0x0431);
extendedKeyCodesSet.add(0x01000000+0x0446);
extendedKeyCodesSet.add(0x01000000+0x0434);
extendedKeyCodesSet.add(0x01000000+0x0435);
extendedKeyCodesSet.add(0x01000000+0x0444);
extendedKeyCodesSet.add(0x01000000+0x0433);
extendedKeyCodesSet.add(0x01000000+0x0445);
extendedKeyCodesSet.add(0x01000000+0x0438);
extendedKeyCodesSet.add(0x01000000+0x0439);
extendedKeyCodesSet.add(0x01000000+0x043A);
extendedKeyCodesSet.add(0x01000000+0x043B);
extendedKeyCodesSet.add(0x01000000+0x043C);
extendedKeyCodesSet.add(0x01000000+0x043D);
extendedKeyCodesSet.add(0x01000000+0x043E);
extendedKeyCodesSet.add(0x01000000+0x043F);
extendedKeyCodesSet.add(0x01000000+0x044F);
extendedKeyCodesSet.add(0x01000000+0x0440);
extendedKeyCodesSet.add(0x01000000+0x0441);
extendedKeyCodesSet.add(0x01000000+0x0442);
extendedKeyCodesSet.add(0x01000000+0x0443);
extendedKeyCodesSet.add(0x01000000+0x0436);
extendedKeyCodesSet.add(0x01000000+0x0432);
extendedKeyCodesSet.add(0x01000000+0x044C);
extendedKeyCodesSet.add(0x01000000+0x044B);
extendedKeyCodesSet.add(0x01000000+0x0437);
extendedKeyCodesSet.add(0x01000000+0x0448);
extendedKeyCodesSet.add(0x01000000+0x044D);
extendedKeyCodesSet.add(0x01000000+0x0449);
extendedKeyCodesSet.add(0x01000000+0x0447);
extendedKeyCodesSet.add(0x01000000+0x044A);
extendedKeyCodesSet.add(0x01000000+0x2015);
extendedKeyCodesSet.add(0x01000000+0x03B1);
extendedKeyCodesSet.add(0x01000000+0x03B2);
extendedKeyCodesSet.add(0x01000000+0x03B3);
extendedKeyCodesSet.add(0x01000000+0x03B4);
extendedKeyCodesSet.add(0x01000000+0x03B5);
extendedKeyCodesSet.add(0x01000000+0x03B6);
extendedKeyCodesSet.add(0x01000000+0x03B7);
extendedKeyCodesSet.add(0x01000000+0x03B8);
extendedKeyCodesSet.add(0x01000000+0x03B9);
extendedKeyCodesSet.add(0x01000000+0x03BA);
extendedKeyCodesSet.add(0x01000000+0x03BB);
extendedKeyCodesSet.add(0x01000000+0x03BC);
extendedKeyCodesSet.add(0x01000000+0x03BD);
extendedKeyCodesSet.add(0x01000000+0x03BE);
extendedKeyCodesSet.add(0x01000000+0x03BF);
extendedKeyCodesSet.add(0x01000000+0x03C0);
extendedKeyCodesSet.add(0x01000000+0x03C1);
extendedKeyCodesSet.add(0x01000000+0x03C3);
extendedKeyCodesSet.add(0x01000000+0x03C2);
extendedKeyCodesSet.add(0x01000000+0x03C4);
extendedKeyCodesSet.add(0x01000000+0x03C5);
extendedKeyCodesSet.add(0x01000000+0x03C6);
extendedKeyCodesSet.add(0x01000000+0x03C7);
extendedKeyCodesSet.add(0x01000000+0x03C8);
extendedKeyCodesSet.add(0x01000000+0x03C9);
extendedKeyCodesSet.add(0x01000000+0x2190);
extendedKeyCodesSet.add(0x01000000+0x2192);
extendedKeyCodesSet.add(0x01000000+0x2193);
extendedKeyCodesSet.add(0x01000000+0x2013);
extendedKeyCodesSet.add(0x01000000+0x201C);
extendedKeyCodesSet.add(0x01000000+0x201D);
extendedKeyCodesSet.add(0x01000000+0x201E);
extendedKeyCodesSet.add(0x01000000+0x05D0);
extendedKeyCodesSet.add(0x01000000+0x05D1);
extendedKeyCodesSet.add(0x01000000+0x05D2);
extendedKeyCodesSet.add(0x01000000+0x05D3);
extendedKeyCodesSet.add(0x01000000+0x05D4);
extendedKeyCodesSet.add(0x01000000+0x05D5);
extendedKeyCodesSet.add(0x01000000+0x05D6);
extendedKeyCodesSet.add(0x01000000+0x05D7);
extendedKeyCodesSet.add(0x01000000+0x05D8);
extendedKeyCodesSet.add(0x01000000+0x05D9);
extendedKeyCodesSet.add(0x01000000+0x05DA);
extendedKeyCodesSet.add(0x01000000+0x05DB);
extendedKeyCodesSet.add(0x01000000+0x05DC);
extendedKeyCodesSet.add(0x01000000+0x05DD);
extendedKeyCodesSet.add(0x01000000+0x05DE);
extendedKeyCodesSet.add(0x01000000+0x05DF);
extendedKeyCodesSet.add(0x01000000+0x05E0);
extendedKeyCodesSet.add(0x01000000+0x05E1);
extendedKeyCodesSet.add(0x01000000+0x05E2);
extendedKeyCodesSet.add(0x01000000+0x05E3);
extendedKeyCodesSet.add(0x01000000+0x05E4);
extendedKeyCodesSet.add(0x01000000+0x05E5);
extendedKeyCodesSet.add(0x01000000+0x05E6);
extendedKeyCodesSet.add(0x01000000+0x05E7);
extendedKeyCodesSet.add(0x01000000+0x05E8);
extendedKeyCodesSet.add(0x01000000+0x05E9);
extendedKeyCodesSet.add(0x01000000+0x05EA);
extendedKeyCodesSet.add(0x01000000+0x0E01);
extendedKeyCodesSet.add(0x01000000+0x0E02);
extendedKeyCodesSet.add(0x01000000+0x0E03);
extendedKeyCodesSet.add(0x01000000+0x0E04);
extendedKeyCodesSet.add(0x01000000+0x0E05);
extendedKeyCodesSet.add(0x01000000+0x0E07);
extendedKeyCodesSet.add(0x01000000+0x0E08);
extendedKeyCodesSet.add(0x01000000+0x0E0A);
extendedKeyCodesSet.add(0x01000000+0x0E0C);
extendedKeyCodesSet.add(0x01000000+0x0E14);
extendedKeyCodesSet.add(0x01000000+0x0E15);
extendedKeyCodesSet.add(0x01000000+0x0E16);
extendedKeyCodesSet.add(0x01000000+0x0E17);
extendedKeyCodesSet.add(0x01000000+0x0E19);
extendedKeyCodesSet.add(0x01000000+0x0E1A);
extendedKeyCodesSet.add(0x01000000+0x0E1B);
extendedKeyCodesSet.add(0x01000000+0x0E1C);
extendedKeyCodesSet.add(0x01000000+0x0E1D);
extendedKeyCodesSet.add(0x01000000+0x0E1E);
extendedKeyCodesSet.add(0x01000000+0x0E1F);
extendedKeyCodesSet.add(0x01000000+0x0E20);
extendedKeyCodesSet.add(0x01000000+0x0E21);
extendedKeyCodesSet.add(0x01000000+0x0E22);
extendedKeyCodesSet.add(0x01000000+0x0E23);
extendedKeyCodesSet.add(0x01000000+0x0E25);
extendedKeyCodesSet.add(0x01000000+0x0E27);
extendedKeyCodesSet.add(0x01000000+0x0E2A);
extendedKeyCodesSet.add(0x01000000+0x0E2B);
extendedKeyCodesSet.add(0x01000000+0x0E2D);
extendedKeyCodesSet.add(0x01000000+0x0E30);
extendedKeyCodesSet.add(0x01000000+0x0E31);
extendedKeyCodesSet.add(0x01000000+0x0E32);
extendedKeyCodesSet.add(0x01000000+0x0E33);
extendedKeyCodesSet.add(0x01000000+0x0E34);
extendedKeyCodesSet.add(0x01000000+0x0E35);
extendedKeyCodesSet.add(0x01000000+0x0E36);
extendedKeyCodesSet.add(0x01000000+0x0E37);
extendedKeyCodesSet.add(0x01000000+0x0E38);
extendedKeyCodesSet.add(0x01000000+0x0E39);
extendedKeyCodesSet.add(0x01000000+0x0E3F);
extendedKeyCodesSet.add(0x01000000+0x0E40);
extendedKeyCodesSet.add(0x01000000+0x0E41);
extendedKeyCodesSet.add(0x01000000+0x0E43);
extendedKeyCodesSet.add(0x01000000+0x0E44);
extendedKeyCodesSet.add(0x01000000+0x0E45);
extendedKeyCodesSet.add(0x01000000+0x0E46);
extendedKeyCodesSet.add(0x01000000+0x0E47);
extendedKeyCodesSet.add(0x01000000+0x0E48);
extendedKeyCodesSet.add(0x01000000+0x0E49);
extendedKeyCodesSet.add(0x01000000+0x0E50);
extendedKeyCodesSet.add(0x01000000+0x0E51);
extendedKeyCodesSet.add(0x01000000+0x0E52);
extendedKeyCodesSet.add(0x01000000+0x0E53);
extendedKeyCodesSet.add(0x01000000+0x0E54);
extendedKeyCodesSet.add(0x01000000+0x0E55);
extendedKeyCodesSet.add(0x01000000+0x0E56);
extendedKeyCodesSet.add(0x01000000+0x0E57);
extendedKeyCodesSet.add(0x01000000+0x0E58);
extendedKeyCodesSet.add(0x01000000+0x0E59);
extendedKeyCodesSet.add(0x01000000+0x0587);
extendedKeyCodesSet.add(0x01000000+0x0589);
extendedKeyCodesSet.add(0x01000000+0x0589);
extendedKeyCodesSet.add(0x01000000+0x055D);
extendedKeyCodesSet.add(0x01000000+0x055D);
extendedKeyCodesSet.add(0x01000000+0x055B);
extendedKeyCodesSet.add(0x01000000+0x055B);
extendedKeyCodesSet.add(0x01000000+0x055E);
extendedKeyCodesSet.add(0x01000000+0x055E);
extendedKeyCodesSet.add(0x01000000+0x0561);
extendedKeyCodesSet.add(0x01000000+0x0562);
extendedKeyCodesSet.add(0x01000000+0x0563);
extendedKeyCodesSet.add(0x01000000+0x0564);
extendedKeyCodesSet.add(0x01000000+0x0565);
extendedKeyCodesSet.add(0x01000000+0x0566);
extendedKeyCodesSet.add(0x01000000+0x0567);
extendedKeyCodesSet.add(0x01000000+0x0568);
extendedKeyCodesSet.add(0x01000000+0x0569);
extendedKeyCodesSet.add(0x01000000+0x056A);
extendedKeyCodesSet.add(0x01000000+0x056B);
extendedKeyCodesSet.add(0x01000000+0x056C);
extendedKeyCodesSet.add(0x01000000+0x056D);
extendedKeyCodesSet.add(0x01000000+0x056E);
extendedKeyCodesSet.add(0x01000000+0x056F);
extendedKeyCodesSet.add(0x01000000+0x0570);
extendedKeyCodesSet.add(0x01000000+0x0571);
extendedKeyCodesSet.add(0x01000000+0x0572);
extendedKeyCodesSet.add(0x01000000+0x0573);
extendedKeyCodesSet.add(0x01000000+0x0574);
extendedKeyCodesSet.add(0x01000000+0x0575);
extendedKeyCodesSet.add(0x01000000+0x0576);
extendedKeyCodesSet.add(0x01000000+0x0577);
extendedKeyCodesSet.add(0x01000000+0x0578);
extendedKeyCodesSet.add(0x01000000+0x0579);
extendedKeyCodesSet.add(0x01000000+0x057A);
extendedKeyCodesSet.add(0x01000000+0x057B);
extendedKeyCodesSet.add(0x01000000+0x057C);
extendedKeyCodesSet.add(0x01000000+0x057D);
extendedKeyCodesSet.add(0x01000000+0x057E);
extendedKeyCodesSet.add(0x01000000+0x057F);
extendedKeyCodesSet.add(0x01000000+0x0580);
extendedKeyCodesSet.add(0x01000000+0x0581);
extendedKeyCodesSet.add(0x01000000+0x0582);
extendedKeyCodesSet.add(0x01000000+0x0583);
extendedKeyCodesSet.add(0x01000000+0x0584);
extendedKeyCodesSet.add(0x01000000+0x0585);
extendedKeyCodesSet.add(0x01000000+0x0586);
extendedKeyCodesSet.add(0x01000000+0x10D0);
extendedKeyCodesSet.add(0x01000000+0x10D1);
extendedKeyCodesSet.add(0x01000000+0x10D2);
extendedKeyCodesSet.add(0x01000000+0x10D3);
extendedKeyCodesSet.add(0x01000000+0x10D4);
extendedKeyCodesSet.add(0x01000000+0x10D5);
extendedKeyCodesSet.add(0x01000000+0x10D6);
extendedKeyCodesSet.add(0x01000000+0x10D7);
extendedKeyCodesSet.add(0x01000000+0x10D8);
extendedKeyCodesSet.add(0x01000000+0x10D9);
extendedKeyCodesSet.add(0x01000000+0x10DA);
extendedKeyCodesSet.add(0x01000000+0x10DB);
extendedKeyCodesSet.add(0x01000000+0x10DC);
extendedKeyCodesSet.add(0x01000000+0x10DD);
extendedKeyCodesSet.add(0x01000000+0x10DE);
extendedKeyCodesSet.add(0x01000000+0x10DF);
extendedKeyCodesSet.add(0x01000000+0x10E0);
extendedKeyCodesSet.add(0x01000000+0x10E1);
extendedKeyCodesSet.add(0x01000000+0x10E2);
extendedKeyCodesSet.add(0x01000000+0x10E3);
extendedKeyCodesSet.add(0x01000000+0x10E4);
extendedKeyCodesSet.add(0x01000000+0x10E5);
extendedKeyCodesSet.add(0x01000000+0x10E6);
extendedKeyCodesSet.add(0x01000000+0x10E7);
extendedKeyCodesSet.add(0x01000000+0x10E8);
extendedKeyCodesSet.add(0x01000000+0x10E9);
extendedKeyCodesSet.add(0x01000000+0x10EA);
extendedKeyCodesSet.add(0x01000000+0x10EB);
extendedKeyCodesSet.add(0x01000000+0x10EC);
extendedKeyCodesSet.add(0x01000000+0x10ED);
extendedKeyCodesSet.add(0x01000000+0x10EE);
extendedKeyCodesSet.add(0x01000000+0x10EF);
extendedKeyCodesSet.add(0x01000000+0x10F0);
extendedKeyCodesSet.add(0x01000000+0x01E7);
extendedKeyCodesSet.add(0x01000000+0x0259);
extendedKeyCodesSet.add(0x01000000+0x1EB9);
extendedKeyCodesSet.add(0x01000000+0x1ECB);
extendedKeyCodesSet.add(0x01000000+0x1ECD);
extendedKeyCodesSet.add(0x01000000+0x1EE5);
extendedKeyCodesSet.add(0x01000000+0x01A1);
extendedKeyCodesSet.add(0x01000000+0x01B0);
extendedKeyCodesSet.add(0x01000000+0x20AB);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,121 @@
/*
* Copyright (c) 1996, 2011, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.StandardCharsets;
import sun.nio.cs.HistoricallyNamedCharset;
public class FontDescriptor implements Cloneable {
static {
NativeLibLoader.loadLibraries();
initIDs();
}
String nativeName;
public CharsetEncoder encoder;
String charsetName;
private int[] exclusionRanges;
public FontDescriptor(String nativeName, CharsetEncoder encoder,
int[] exclusionRanges){
this.nativeName = nativeName;
this.encoder = encoder;
this.exclusionRanges = exclusionRanges;
this.useUnicode = false;
Charset cs = encoder.charset();
if (cs instanceof HistoricallyNamedCharset)
this.charsetName = ((HistoricallyNamedCharset)cs).historicalName();
else
this.charsetName = cs.name();
}
public String getNativeName() {
return nativeName;
}
public CharsetEncoder getFontCharsetEncoder() {
return encoder;
}
public String getFontCharsetName() {
return charsetName;
}
public int[] getExclusionRanges() {
return exclusionRanges;
}
/**
* Return true if the character is exclusion character.
*/
public boolean isExcluded(char ch){
for (int i = 0; i < exclusionRanges.length; ){
int lo = (exclusionRanges[i++]);
int up = (exclusionRanges[i++]);
if (ch >= lo && ch <= up){
return true;
}
}
return false;
}
public String toString() {
return super.toString() + " [" + nativeName + "|" + encoder + "]";
}
/**
* Initialize JNI field and method IDs
*/
private static native void initIDs();
public CharsetEncoder unicodeEncoder;
boolean useUnicode; // set to true from native code on Unicode-based systems
public boolean useUnicode() {
if (useUnicode && unicodeEncoder == null) {
try {
this.unicodeEncoder = isLE?
StandardCharsets.UTF_16LE.newEncoder():
StandardCharsets.UTF_16BE.newEncoder();
} catch (IllegalArgumentException x) {}
}
return useUnicode;
}
static boolean isLE;
static {
String enc = (String) java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("sun.io.unicode.encoding",
"UnicodeBig"));
isLE = !"UnicodeBig".equals(enc);
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2013, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.*;
/**
* An interface for the EventQueue delegate.
* This class is added to support JavaFX/AWT interop single threaded mode
* The delegate should be set in EventQueue by {@link EventQueue#setFwDispatcher(FwDispatcher)}
* If the delegate is not null, than it handles supported methods instead of the
* event queue. If it is null than the behaviour of an event queue does not change.
*
* @see EventQueue
*
* @author Petr Pchelko
*
* @since 1.8
*/
public interface FwDispatcher {
/**
* Delegates the {@link EventQueue#isDispatchThread()} method
*/
boolean isDispatchThread();
/**
* Forwards a runnable to the delegate, which executes it on an appropriate thread.
* @param r - a runnable calling {@link EventQueue#dispatchEventImpl(java.awt.AWTEvent, Object)}
*/
void scheduleDispatch(Runnable r);
/**
* Delegates the {@link java.awt.EventQueue#createSecondaryLoop()} method
*/
SecondaryLoop createSecondaryLoop();
}

View File

@@ -0,0 +1,216 @@
/*
* Copyright (c) 1999, 2013, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.InvocationEvent;
/**
* A stateless class which responds to native mouse moves, Component resizes,
* Component moves, showing and hiding of Components, minimizing and
* maximizing of top level Windows, addition and removal of Components,
* and calls to setCursor().
*/
public abstract class GlobalCursorManager {
class NativeUpdater implements Runnable {
boolean pending = false;
public void run() {
boolean shouldUpdate = false;
synchronized (this) {
if (pending) {
pending = false;
shouldUpdate = true;
}
}
if (shouldUpdate) {
_updateCursor(false);
}
}
public void postIfNotPending(Component heavy, InvocationEvent in) {
boolean shouldPost = false;
synchronized (this) {
if (!pending) {
pending = shouldPost = true;
}
}
if (shouldPost) {
SunToolkit.postEvent(SunToolkit.targetToAppContext(heavy), in);
}
}
}
/**
* Use a singleton NativeUpdater for better performance. We cannot use
* a singleton InvocationEvent because we want each event to have a fresh
* timestamp.
*/
private final NativeUpdater nativeUpdater = new NativeUpdater();
/**
* The last time the cursor was updated, in milliseconds.
*/
private long lastUpdateMillis;
/**
* Locking object for synchronizing access to lastUpdateMillis. The VM
* does not guarantee atomicity of longs.
*/
private final Object lastUpdateLock = new Object();
/**
* Should be called for any activity at the Java level which may affect
* the global cursor, except for Java MOUSE_MOVED events.
*/
public void updateCursorImmediately() {
synchronized (nativeUpdater) {
nativeUpdater.pending = false;
}
_updateCursor(false);
}
/**
* Should be called in response to Java MOUSE_MOVED events. The update
* will be discarded if the InputEvent is outdated.
*
* @param e the InputEvent which triggered the cursor update.
*/
public void updateCursorImmediately(InputEvent e) {
boolean shouldUpdate;
synchronized (lastUpdateLock) {
shouldUpdate = (e.getWhen() >= lastUpdateMillis);
}
if (shouldUpdate) {
_updateCursor(true);
}
}
/**
* Should be called in response to a native mouse enter or native mouse
* button released message. Should not be called during a mouse drag.
*/
public void updateCursorLater(Component heavy) {
nativeUpdater.postIfNotPending(heavy, new InvocationEvent
(Toolkit.getDefaultToolkit(), nativeUpdater));
}
protected GlobalCursorManager() { }
/**
* Set the global cursor to the specified cursor. The component over
* which the Cursor current resides is provided as a convenience. Not
* all platforms may require the Component.
*/
protected abstract void setCursor(Component comp, Cursor cursor,
boolean useCache);
/**
* Returns the global cursor position, in screen coordinates.
*/
protected abstract void getCursorPos(Point p);
protected abstract Point getLocationOnScreen(Component com);
/**
* Returns the most specific, visible, heavyweight Component
* under the cursor. This method should return null iff the cursor is
* not over any Java Window.
*
* @param useCache If true, the implementation is free to use caching
* mechanisms because the Z-order, visibility, and enabled state of the
* Components has not changed. If false, the implementation should not
* make these assumptions.
*/
protected abstract Component findHeavyweightUnderCursor(boolean useCache);
/**
* Updates the global cursor. We apply a three-step scheme to cursor
* updates:<p>
*
* (1) InputEvent updates which are outdated are discarded by
* <code>updateCursorImmediately(InputEvent)</code>.<p>
*
* (2) If 'useCache' is true, the native code is free to use a cached
* value to determine the most specific, visible, enabled heavyweight
* because this update is occurring in response to a mouse move. If
* 'useCache' is false, the native code must perform a new search given
* the current mouse coordinates.
*
* (3) Once we have determined the most specific, visible, enabled
* heavyweight, we use findComponentAt to find the most specific, visible,
* enabled Component.
*/
private void _updateCursor(boolean useCache) {
synchronized (lastUpdateLock) {
lastUpdateMillis = System.currentTimeMillis();
}
Point queryPos = null, p = null;
Component comp;
try {
comp = findHeavyweightUnderCursor(useCache);
if (comp == null) {
updateCursorOutOfJava();
return;
}
if (comp instanceof Window) {
p = AWTAccessor.getComponentAccessor().getLocation(comp);
} else if (comp instanceof Container) {
p = getLocationOnScreen(comp);
}
if (p != null) {
queryPos = new Point();
getCursorPos(queryPos);
Component c = AWTAccessor.getContainerAccessor().
findComponentAt((Container) comp,
queryPos.x - p.x, queryPos.y - p.y, false);
// If findComponentAt returns null, then something bad has
// happened. For example, the heavyweight Component may
// have been hidden or disabled by another thread. In that
// case, we'll just use the originial heavyweight.
if (c != null) {
comp = c;
}
}
setCursor(comp, AWTAccessor.getComponentAccessor().getCursor(comp), useCache);
} catch (IllegalComponentStateException e) {
// Shouldn't happen, but if it does, abort.
}
}
protected void updateCursorOutOfJava() {
// Cursor is not over a Java Window. Do nothing...usually
// But we need to update it in case of grab on X.
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) 1999, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.Color;
public interface Graphics2Delegate {
void setBackground(Color color);
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2005, 2010, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CharsetDecoder;
/* 2d/XMap and WFontConfiguration implementation need access HKSCS,
make a subclass here to avoid expose HKSCS to the public in
ExtendedCharsets class, because if we want to have a public HKSCS,
it probably should be HKSCS_2001 not HKSCS.
*/
public class HKSCS extends sun.nio.cs.ext.MS950_HKSCS_XP {
public HKSCS () {
super();
}
public boolean contains(Charset cs) {
return (cs instanceof HKSCS);
}
}

View File

@@ -0,0 +1,392 @@
/*
* Copyright (c) 2011, 2014, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import sun.awt.datatransfer.DataTransferer;
import java.awt.*;
import java.awt.dnd.*;
import java.awt.dnd.peer.DragSourceContextPeer;
import java.awt.im.InputMethodHighlight;
import java.awt.im.spi.InputMethodDescriptor;
import java.awt.image.*;
import java.awt.datatransfer.Clipboard;
import java.awt.peer.*;
import java.util.Map;
import java.util.Properties;
/*
* HToolkit is a platform independent Toolkit used
* with the HeadlessToolkit. It is primarily used
* in embedded JRE's that do not have sun/awt/X11 classes.
*/
public class HToolkit extends SunToolkit
implements ComponentFactory {
private static final KeyboardFocusManagerPeer kfmPeer = new KeyboardFocusManagerPeer() {
public void setCurrentFocusedWindow(Window win) {}
public Window getCurrentFocusedWindow() { return null; }
public void setCurrentFocusOwner(Component comp) {}
public Component getCurrentFocusOwner() { return null; }
public void clearGlobalFocusOwner(Window activeWindow) {}
};
public HToolkit() {
}
/*
* Component peer objects - unsupported.
*/
public WindowPeer createWindow(Window target)
throws HeadlessException {
throw new HeadlessException();
}
public FramePeer createLightweightFrame(LightweightFrame target)
throws HeadlessException {
throw new HeadlessException();
}
public FramePeer createFrame(Frame target)
throws HeadlessException {
throw new HeadlessException();
}
public DialogPeer createDialog(Dialog target)
throws HeadlessException {
throw new HeadlessException();
}
public ButtonPeer createButton(Button target)
throws HeadlessException {
throw new HeadlessException();
}
public TextFieldPeer createTextField(TextField target)
throws HeadlessException {
throw new HeadlessException();
}
public ChoicePeer createChoice(Choice target)
throws HeadlessException {
throw new HeadlessException();
}
public LabelPeer createLabel(Label target)
throws HeadlessException {
throw new HeadlessException();
}
public ListPeer createList(List target)
throws HeadlessException {
throw new HeadlessException();
}
public CheckboxPeer createCheckbox(Checkbox target)
throws HeadlessException {
throw new HeadlessException();
}
public ScrollbarPeer createScrollbar(Scrollbar target)
throws HeadlessException {
throw new HeadlessException();
}
public ScrollPanePeer createScrollPane(ScrollPane target)
throws HeadlessException {
throw new HeadlessException();
}
public TextAreaPeer createTextArea(TextArea target)
throws HeadlessException {
throw new HeadlessException();
}
public FileDialogPeer createFileDialog(FileDialog target)
throws HeadlessException {
throw new HeadlessException();
}
public MenuBarPeer createMenuBar(MenuBar target)
throws HeadlessException {
throw new HeadlessException();
}
public MenuPeer createMenu(Menu target)
throws HeadlessException {
throw new HeadlessException();
}
public PopupMenuPeer createPopupMenu(PopupMenu target)
throws HeadlessException {
throw new HeadlessException();
}
public MenuItemPeer createMenuItem(MenuItem target)
throws HeadlessException {
throw new HeadlessException();
}
public CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target)
throws HeadlessException {
throw new HeadlessException();
}
public DragSourceContextPeer createDragSourceContextPeer(
DragGestureEvent dge)
throws InvalidDnDOperationException {
throw new InvalidDnDOperationException("Headless environment");
}
public RobotPeer createRobot(Robot target, GraphicsDevice screen)
throws AWTException, HeadlessException {
throw new HeadlessException();
}
public KeyboardFocusManagerPeer getKeyboardFocusManagerPeer() {
// See 6833019.
return kfmPeer;
}
public TrayIconPeer createTrayIcon(TrayIcon target)
throws HeadlessException {
throw new HeadlessException();
}
public SystemTrayPeer createSystemTray(SystemTray target)
throws HeadlessException {
throw new HeadlessException();
}
public boolean isTraySupported() {
return false;
}
@Override
public DataTransferer getDataTransferer() {
return null;
}
public GlobalCursorManager getGlobalCursorManager()
throws HeadlessException {
throw new HeadlessException();
}
/*
* Headless toolkit - unsupported.
*/
protected void loadSystemColors(int[] systemColors)
throws HeadlessException {
throw new HeadlessException();
}
public ColorModel getColorModel()
throws HeadlessException {
throw new HeadlessException();
}
public int getScreenResolution()
throws HeadlessException {
throw new HeadlessException();
}
public Map mapInputMethodHighlight(InputMethodHighlight highlight)
throws HeadlessException {
throw new HeadlessException();
}
public int getMenuShortcutKeyMask()
throws HeadlessException {
throw new HeadlessException();
}
public boolean getLockingKeyState(int keyCode)
throws UnsupportedOperationException {
throw new HeadlessException();
}
public void setLockingKeyState(int keyCode, boolean on)
throws UnsupportedOperationException {
throw new HeadlessException();
}
public Cursor createCustomCursor(Image cursor, Point hotSpot, String name)
throws IndexOutOfBoundsException, HeadlessException {
throw new HeadlessException();
}
public Dimension getBestCursorSize(int preferredWidth, int preferredHeight)
throws HeadlessException {
throw new HeadlessException();
}
public int getMaximumCursorColors()
throws HeadlessException {
throw new HeadlessException();
}
public <T extends DragGestureRecognizer> T
createDragGestureRecognizer(Class<T> abstractRecognizerClass,
DragSource ds, Component c,
int srcActions, DragGestureListener dgl)
{
return null;
}
public int getScreenHeight()
throws HeadlessException {
throw new HeadlessException();
}
public int getScreenWidth()
throws HeadlessException {
throw new HeadlessException();
}
public Dimension getScreenSize()
throws HeadlessException {
throw new HeadlessException();
}
public Insets getScreenInsets(GraphicsConfiguration gc)
throws HeadlessException {
throw new HeadlessException();
}
public void setDynamicLayout(boolean dynamic)
throws HeadlessException {
throw new HeadlessException();
}
protected boolean isDynamicLayoutSet()
throws HeadlessException {
throw new HeadlessException();
}
public boolean isDynamicLayoutActive()
throws HeadlessException {
throw new HeadlessException();
}
public Clipboard getSystemClipboard()
throws HeadlessException {
throw new HeadlessException();
}
/*
* Printing
*/
public PrintJob getPrintJob(Frame frame, String jobtitle,
JobAttributes jobAttributes,
PageAttributes pageAttributes) {
if (frame != null) {
// Should never happen
throw new HeadlessException();
}
throw new IllegalArgumentException(
"PrintJob not supported in a headless environment");
}
public PrintJob getPrintJob(Frame frame, String doctitle, Properties props)
{
if (frame != null) {
// Should never happen
throw new HeadlessException();
}
throw new IllegalArgumentException(
"PrintJob not supported in a headless environment");
}
/*
* Headless toolkit - supported.
*/
public void sync() {
// Do nothing
}
protected boolean syncNativeQueue(final long timeout) {
return false;
}
public void beep() {
// Send alert character
System.out.write(0x07);
}
/*
* Fonts
*/
public FontPeer getFontPeer(String name, int style) {
return (FontPeer)null;
}
/*
* Modality
*/
public boolean isModalityTypeSupported(Dialog.ModalityType modalityType) {
return false;
}
public boolean isModalExclusionTypeSupported(Dialog.ModalExclusionType exclusionType) {
return false;
}
public boolean isDesktopSupported() {
return false;
}
public DesktopPeer createDesktopPeer(Desktop target)
throws HeadlessException{
throw new HeadlessException();
}
public boolean isWindowOpacityControlSupported() {
return false;
}
public boolean isWindowShapingSupported() {
return false;
}
public boolean isWindowTranslucencySupported() {
return false;
}
public void grab(Window w) { }
public void ungrab(Window w) { }
protected boolean syncNativeQueue() { return false; }
public InputMethodDescriptor getInputMethodAdapterDescriptor()
throws AWTException
{
return (InputMethodDescriptor)null;
}
}

View File

@@ -0,0 +1,486 @@
/*
* Copyright (c) 2000, 2012, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import sun.awt.datatransfer.DataTransferer;
import java.awt.*;
import java.awt.dnd.*;
import java.awt.dnd.peer.DragSourceContextPeer;
import java.awt.event.*;
import java.awt.im.InputMethodHighlight;
import java.awt.image.*;
import java.awt.datatransfer.Clipboard;
import java.awt.peer.*;
import java.beans.PropertyChangeListener;
import java.net.URL;
import java.util.Map;
import java.util.Properties;
public class HeadlessToolkit extends Toolkit
implements ComponentFactory, KeyboardFocusManagerPeerProvider {
private static final KeyboardFocusManagerPeer kfmPeer = new KeyboardFocusManagerPeer() {
public void setCurrentFocusedWindow(Window win) {}
public Window getCurrentFocusedWindow() { return null; }
public void setCurrentFocusOwner(Component comp) {}
public Component getCurrentFocusOwner() { return null; }
public void clearGlobalFocusOwner(Window activeWindow) {}
};
private Toolkit tk;
private ComponentFactory componentFactory;
public HeadlessToolkit(Toolkit tk) {
this.tk = tk;
if (tk instanceof ComponentFactory) {
componentFactory = (ComponentFactory)tk;
}
}
public Toolkit getUnderlyingToolkit() {
return tk;
}
/*
* Component peer objects.
*/
/* Lightweight implementation of Canvas and Panel */
public CanvasPeer createCanvas(Canvas target) {
return (CanvasPeer)createComponent(target);
}
public PanelPeer createPanel(Panel target) {
return (PanelPeer)createComponent(target);
}
/*
* Component peer objects - unsupported.
*/
public WindowPeer createWindow(Window target)
throws HeadlessException {
throw new HeadlessException();
}
public FramePeer createFrame(Frame target)
throws HeadlessException {
throw new HeadlessException();
}
public DialogPeer createDialog(Dialog target)
throws HeadlessException {
throw new HeadlessException();
}
public ButtonPeer createButton(Button target)
throws HeadlessException {
throw new HeadlessException();
}
public TextFieldPeer createTextField(TextField target)
throws HeadlessException {
throw new HeadlessException();
}
public ChoicePeer createChoice(Choice target)
throws HeadlessException {
throw new HeadlessException();
}
public LabelPeer createLabel(Label target)
throws HeadlessException {
throw new HeadlessException();
}
public ListPeer createList(List target)
throws HeadlessException {
throw new HeadlessException();
}
public CheckboxPeer createCheckbox(Checkbox target)
throws HeadlessException {
throw new HeadlessException();
}
public ScrollbarPeer createScrollbar(Scrollbar target)
throws HeadlessException {
throw new HeadlessException();
}
public ScrollPanePeer createScrollPane(ScrollPane target)
throws HeadlessException {
throw new HeadlessException();
}
public TextAreaPeer createTextArea(TextArea target)
throws HeadlessException {
throw new HeadlessException();
}
public FileDialogPeer createFileDialog(FileDialog target)
throws HeadlessException {
throw new HeadlessException();
}
public MenuBarPeer createMenuBar(MenuBar target)
throws HeadlessException {
throw new HeadlessException();
}
public MenuPeer createMenu(Menu target)
throws HeadlessException {
throw new HeadlessException();
}
public PopupMenuPeer createPopupMenu(PopupMenu target)
throws HeadlessException {
throw new HeadlessException();
}
public MenuItemPeer createMenuItem(MenuItem target)
throws HeadlessException {
throw new HeadlessException();
}
public CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target)
throws HeadlessException {
throw new HeadlessException();
}
public DragSourceContextPeer createDragSourceContextPeer(
DragGestureEvent dge)
throws InvalidDnDOperationException {
throw new InvalidDnDOperationException("Headless environment");
}
public RobotPeer createRobot(Robot target, GraphicsDevice screen)
throws AWTException, HeadlessException {
throw new HeadlessException();
}
public KeyboardFocusManagerPeer getKeyboardFocusManagerPeer() {
// See 6833019.
return kfmPeer;
}
public TrayIconPeer createTrayIcon(TrayIcon target)
throws HeadlessException {
throw new HeadlessException();
}
public SystemTrayPeer createSystemTray(SystemTray target)
throws HeadlessException {
throw new HeadlessException();
}
public boolean isTraySupported() {
return false;
}
public GlobalCursorManager getGlobalCursorManager()
throws HeadlessException {
throw new HeadlessException();
}
/*
* Headless toolkit - unsupported.
*/
protected void loadSystemColors(int[] systemColors)
throws HeadlessException {
throw new HeadlessException();
}
public ColorModel getColorModel()
throws HeadlessException {
throw new HeadlessException();
}
public int getScreenResolution()
throws HeadlessException {
throw new HeadlessException();
}
public Map mapInputMethodHighlight(InputMethodHighlight highlight)
throws HeadlessException {
throw new HeadlessException();
}
public int getMenuShortcutKeyMask()
throws HeadlessException {
throw new HeadlessException();
}
public boolean getLockingKeyState(int keyCode)
throws UnsupportedOperationException {
throw new HeadlessException();
}
public void setLockingKeyState(int keyCode, boolean on)
throws UnsupportedOperationException {
throw new HeadlessException();
}
public Cursor createCustomCursor(Image cursor, Point hotSpot, String name)
throws IndexOutOfBoundsException, HeadlessException {
throw new HeadlessException();
}
public Dimension getBestCursorSize(int preferredWidth, int preferredHeight)
throws HeadlessException {
throw new HeadlessException();
}
public int getMaximumCursorColors()
throws HeadlessException {
throw new HeadlessException();
}
public <T extends DragGestureRecognizer> T
createDragGestureRecognizer(Class<T> abstractRecognizerClass,
DragSource ds, Component c,
int srcActions, DragGestureListener dgl)
{
return null;
}
public int getScreenHeight()
throws HeadlessException {
throw new HeadlessException();
}
public int getScreenWidth()
throws HeadlessException {
throw new HeadlessException();
}
public Dimension getScreenSize()
throws HeadlessException {
throw new HeadlessException();
}
public Insets getScreenInsets(GraphicsConfiguration gc)
throws HeadlessException {
throw new HeadlessException();
}
public void setDynamicLayout(boolean dynamic)
throws HeadlessException {
throw new HeadlessException();
}
protected boolean isDynamicLayoutSet()
throws HeadlessException {
throw new HeadlessException();
}
public boolean isDynamicLayoutActive()
throws HeadlessException {
throw new HeadlessException();
}
public Clipboard getSystemClipboard()
throws HeadlessException {
throw new HeadlessException();
}
/*
* Printing
*/
public PrintJob getPrintJob(Frame frame, String jobtitle,
JobAttributes jobAttributes,
PageAttributes pageAttributes) {
if (frame != null) {
// Should never happen
throw new HeadlessException();
}
throw new NullPointerException("frame must not be null");
}
public PrintJob getPrintJob(Frame frame, String doctitle, Properties props)
{
if (frame != null) {
// Should never happen
throw new HeadlessException();
}
throw new NullPointerException("frame must not be null");
}
/*
* Headless toolkit - supported.
*/
public void sync() {
// Do nothing
}
public void beep() {
// Send alert character
System.out.write(0x07);
}
/*
* Event Queue
*/
public EventQueue getSystemEventQueueImpl() {
return SunToolkit.getSystemEventQueueImplPP();
}
/*
* Images.
*/
public int checkImage(Image img, int w, int h, ImageObserver o) {
return tk.checkImage(img, w, h, o);
}
public boolean prepareImage(
Image img, int w, int h, ImageObserver o) {
return tk.prepareImage(img, w, h, o);
}
public Image getImage(String filename) {
return tk.getImage(filename);
}
public Image getImage(URL url) {
return tk.getImage(url);
}
public Image createImage(String filename) {
return tk.createImage(filename);
}
public Image createImage(URL url) {
return tk.createImage(url);
}
public Image createImage(byte[] data, int offset, int length) {
return tk.createImage(data, offset, length);
}
public Image createImage(ImageProducer producer) {
return tk.createImage(producer);
}
public Image createImage(byte[] imagedata) {
return tk.createImage(imagedata);
}
/*
* Fonts
*/
@SuppressWarnings("deprecation")
public FontPeer getFontPeer(String name, int style) {
if (componentFactory != null) {
return componentFactory.getFontPeer(name, style);
}
return null;
}
@Override
public DataTransferer getDataTransferer() {
return null;
}
@SuppressWarnings("deprecation")
public FontMetrics getFontMetrics(Font font) {
return tk.getFontMetrics(font);
}
@SuppressWarnings("deprecation")
public String[] getFontList() {
return tk.getFontList();
}
/*
* Desktop properties
*/
public void addPropertyChangeListener(String name,
PropertyChangeListener pcl) {
tk.addPropertyChangeListener(name, pcl);
}
public void removePropertyChangeListener(String name,
PropertyChangeListener pcl) {
tk.removePropertyChangeListener(name, pcl);
}
/*
* Modality
*/
public boolean isModalityTypeSupported(Dialog.ModalityType modalityType) {
return false;
}
public boolean isModalExclusionTypeSupported(Dialog.ModalExclusionType exclusionType) {
return false;
}
/*
* Always on top
*/
public boolean isAlwaysOnTopSupported() {
return false;
}
/*
* AWT Event listeners
*/
public void addAWTEventListener(AWTEventListener listener,
long eventMask) {
tk.addAWTEventListener(listener, eventMask);
}
public void removeAWTEventListener(AWTEventListener listener) {
tk.removeAWTEventListener(listener);
}
public AWTEventListener[] getAWTEventListeners() {
return tk.getAWTEventListeners();
}
public AWTEventListener[] getAWTEventListeners(long eventMask) {
return tk.getAWTEventListeners(eventMask);
}
public boolean isDesktopSupported() {
return false;
}
public DesktopPeer createDesktopPeer(Desktop target)
throws HeadlessException{
throw new HeadlessException();
}
public boolean areExtraMouseButtonsEnabled() throws HeadlessException{
throw new HeadlessException();
}
}

View File

@@ -0,0 +1,237 @@
/*
* Copyright (c) 2006, 2013, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.*;
import java.awt.color.*;
import java.awt.image.*;
import sun.awt.image.ToolkitImage;
import sun.awt.image.ImageRepresentation;
import java.util.Arrays;
public class IconInfo {
/**
* Representation of image as an int array.
* It's used on platforms where icon data
* is expected to be in 32-bit format.
*/
private int[] intIconData;
/**
* Representation of image as an long array.
* It's used on platforms where icon data
* is expected to be in 64-bit format.
*/
private long[] longIconData;
/**
* Icon image.
*/
private Image image;
/**
* Width of icon image. Being set in constructor.
*/
private final int width;
/**
* Height of icon image. Being set in constructor.
*/
private final int height;
/**
* Width of scaled icon image. Can be set in setScaledDimension.
*/
private int scaledWidth;
/**
* Height of scaled icon image. Can be set in setScaledDimension.
*/
private int scaledHeight;
/**
* Length of raw data. Being set in constructor / setScaledDimension.
*/
private int rawLength;
public IconInfo(int[] intIconData) {
this.intIconData =
(null == intIconData) ? null : Arrays.copyOf(intIconData, intIconData.length);
this.width = intIconData[0];
this.height = intIconData[1];
this.scaledWidth = width;
this.scaledHeight = height;
this.rawLength = width * height + 2;
}
public IconInfo(long[] longIconData) {
this.longIconData =
(null == longIconData) ? null : Arrays.copyOf(longIconData, longIconData.length);
this.width = (int)longIconData[0];
this.height = (int)longIconData[1];
this.scaledWidth = width;
this.scaledHeight = height;
this.rawLength = width * height + 2;
}
public IconInfo(Image image) {
this.image = image;
if (image instanceof ToolkitImage) {
ImageRepresentation ir = ((ToolkitImage)image).getImageRep();
ir.reconstruct(ImageObserver.ALLBITS);
this.width = ir.getWidth();
this.height = ir.getHeight();
} else {
this.width = image.getWidth(null);
this.height = image.getHeight(null);
}
this.scaledWidth = width;
this.scaledHeight = height;
this.rawLength = width * height + 2;
}
/*
* It sets size of scaled icon.
*/
public void setScaledSize(int width, int height) {
this.scaledWidth = width;
this.scaledHeight = height;
this.rawLength = width * height + 2;
}
public boolean isValid() {
return (width > 0 && height > 0);
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public String toString() {
return "IconInfo[w=" + width + ",h=" + height + ",sw=" + scaledWidth + ",sh=" + scaledHeight + "]";
}
public int getRawLength() {
return rawLength;
}
public int[] getIntData() {
if (this.intIconData == null) {
if (this.longIconData != null) {
this.intIconData = longArrayToIntArray(longIconData);
} else if (this.image != null) {
this.intIconData = imageToIntArray(this.image, scaledWidth, scaledHeight);
}
}
return this.intIconData;
}
public long[] getLongData() {
if (this.longIconData == null) {
if (this.intIconData != null) {
this.longIconData = intArrayToLongArray(this.intIconData);
} else if (this.image != null) {
int[] intIconData = imageToIntArray(this.image, scaledWidth, scaledHeight);
this.longIconData = intArrayToLongArray(intIconData);
}
}
return this.longIconData;
}
public Image getImage() {
if (this.image == null) {
if (this.intIconData != null) {
this.image = intArrayToImage(this.intIconData);
} else if (this.longIconData != null) {
int[] intIconData = longArrayToIntArray(this.longIconData);
this.image = intArrayToImage(intIconData);
}
}
return this.image;
}
private static int[] longArrayToIntArray(long[] longData) {
int[] intData = new int[longData.length];
for (int i = 0; i < longData.length; i++) {
// Such a conversion is valid since the
// original data (see
// make/sun/xawt/ToBin.java) were ints
intData[i] = (int)longData[i];
}
return intData;
}
private static long[] intArrayToLongArray(int[] intData) {
long[] longData = new long[intData.length];
for (int i = 0; i < intData.length; i++) {
longData[i] = (int)intData[i];
}
return longData;
}
static Image intArrayToImage(int[] raw) {
ColorModel cm =
new DirectColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), 32,
0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000,
false, DataBuffer.TYPE_INT);
DataBuffer buffer = new DataBufferInt(raw, raw.length-2, 2);
WritableRaster raster =
Raster.createPackedRaster(buffer, raw[0], raw[1],
raw[0],
new int[] {0x00ff0000, 0x0000ff00,
0x000000ff, 0xff000000},
null);
BufferedImage im = new BufferedImage(cm, raster, false, null);
return im;
}
/*
* Returns array of integers which holds data for the image.
* It scales the image if necessary.
*/
static int[] imageToIntArray(Image image, int width, int height) {
if (width <= 0 || height <= 0) {
return null;
}
ColorModel cm =
new DirectColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), 32,
0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000,
false, DataBuffer.TYPE_INT);
DataBufferInt buffer = new DataBufferInt(width * height);
WritableRaster raster =
Raster.createPackedRaster(buffer, width, height,
width,
new int[] {0x00ff0000, 0x0000ff00,
0x000000ff, 0xff000000},
null);
BufferedImage im = new BufferedImage(cm, raster, false, null);
Graphics g = im.getGraphics();
g.drawImage(image, 0, 0, width, height, null);
g.dispose();
int[] data = buffer.getData();
int[] raw = new int[width * height + 2];
raw[0] = width;
raw[1] = height;
System.arraycopy(data, 0, raw, 2, width * height);
return raw;
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 2000, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.AWTException;
import java.awt.Window;
import java.awt.im.spi.InputMethodDescriptor;
import java.util.Locale;
import sun.awt.im.InputContext;
/**
* Input method support for toolkits
*/
public interface InputMethodSupport {
/**
* Returns a new input method adapter descriptor for native input methods.
*/
InputMethodDescriptor getInputMethodAdapterDescriptor()
throws AWTException;
/**
* Returns a new input method window for the platform
*/
Window createInputMethodWindow(String title, InputContext context);
/**
* Returns whether input methods are enabled on the platform
*/
boolean enableInputMethodsForTextComponent();
/**
* Returns the default keyboard locale of the underlying operating system.
*/
Locale getDefaultKeyboardLocale();
}

View File

@@ -0,0 +1,181 @@
/*
* Copyright (c) 2003, 2013, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.Component;
import java.awt.KeyboardFocusManager;
import java.awt.Window;
import java.awt.Canvas;
import java.awt.Scrollbar;
import java.awt.Panel;
import java.awt.event.FocusEvent;
import java.awt.peer.KeyboardFocusManagerPeer;
import java.awt.peer.ComponentPeer;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import sun.util.logging.PlatformLogger;
public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManagerPeer {
private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.focus.KeyboardFocusManagerPeerImpl");
private static class KfmAccessor {
private static AWTAccessor.KeyboardFocusManagerAccessor instance =
AWTAccessor.getKeyboardFocusManagerAccessor();
}
// The constants are copied from java.awt.KeyboardFocusManager
public static final int SNFH_FAILURE = 0;
public static final int SNFH_SUCCESS_HANDLED = 1;
public static final int SNFH_SUCCESS_PROCEED = 2;
@Override
public void clearGlobalFocusOwner(Window activeWindow) {
if (activeWindow != null) {
Component focusOwner = activeWindow.getFocusOwner();
if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
focusLog.fine("Clearing global focus owner " + focusOwner);
}
if (focusOwner != null) {
FocusEvent fl = new CausedFocusEvent(focusOwner, FocusEvent.FOCUS_LOST, false, null,
CausedFocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
SunToolkit.postPriorityEvent(fl);
}
}
}
/*
* WARNING: Don't call it on the Toolkit thread.
*
* Checks if the component:
* 1) accepts focus on click (in general)
* 2) may be a focus owner (in particular)
*/
@SuppressWarnings("deprecation")
public static boolean shouldFocusOnClick(Component component) {
boolean acceptFocusOnClick = false;
// A component is generally allowed to accept focus on click
// if its peer is focusable. There're some exceptions though.
// CANVAS & SCROLLBAR accept focus on click
if (component instanceof Canvas ||
component instanceof Scrollbar)
{
acceptFocusOnClick = true;
// PANEL, empty only, accepts focus on click
} else if (component instanceof Panel) {
acceptFocusOnClick = (((Panel)component).getComponentCount() == 0);
// Other components
} else {
ComponentPeer peer = (component != null ? component.getPeer() : null);
acceptFocusOnClick = (peer != null ? peer.isFocusable() : false);
}
return acceptFocusOnClick &&
AWTAccessor.getComponentAccessor().canBeFocusOwner(component);
}
/*
* Posts proper lost/gain focus events to the event queue.
*/
@SuppressWarnings("deprecation")
public static boolean deliverFocus(Component lightweightChild,
Component target,
boolean temporary,
boolean focusedWindowChangeAllowed,
long time,
CausedFocusEvent.Cause cause,
Component currentFocusOwner) // provided by the descendant peers
{
if (lightweightChild == null) {
lightweightChild = target;
}
Component currentOwner = currentFocusOwner;
if (currentOwner != null && currentOwner.getPeer() == null) {
currentOwner = null;
}
if (currentOwner != null) {
FocusEvent fl = new CausedFocusEvent(currentOwner, FocusEvent.FOCUS_LOST,
false, lightweightChild, cause);
if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
focusLog.finer("Posting focus event: " + fl);
}
SunToolkit.postEvent(SunToolkit.targetToAppContext(currentOwner), fl);
}
FocusEvent fg = new CausedFocusEvent(lightweightChild, FocusEvent.FOCUS_GAINED,
false, currentOwner, cause);
if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
focusLog.finer("Posting focus event: " + fg);
}
SunToolkit.postEvent(SunToolkit.targetToAppContext(lightweightChild), fg);
return true;
}
// WARNING: Don't call it on the Toolkit thread.
public static boolean requestFocusFor(Component target, CausedFocusEvent.Cause cause) {
return AWTAccessor.getComponentAccessor().requestFocus(target, cause);
}
// WARNING: Don't call it on the Toolkit thread.
public static int shouldNativelyFocusHeavyweight(Component heavyweight,
Component descendant,
boolean temporary,
boolean focusedWindowChangeAllowed,
long time,
CausedFocusEvent.Cause cause)
{
return KfmAccessor.instance.shouldNativelyFocusHeavyweight(
heavyweight, descendant, temporary, focusedWindowChangeAllowed,
time, cause);
}
public static void removeLastFocusRequest(Component heavyweight) {
KfmAccessor.instance.removeLastFocusRequest(heavyweight);
}
// WARNING: Don't call it on the Toolkit thread.
public static boolean processSynchronousLightweightTransfer(Component heavyweight,
Component descendant,
boolean temporary,
boolean focusedWindowChangeAllowed,
long time)
{
return KfmAccessor.instance.processSynchronousLightweightTransfer(
heavyweight, descendant, temporary, focusedWindowChangeAllowed,
time);
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2007, 2012, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.peer.KeyboardFocusManagerPeer;
/**
* {@link KeyboardFocusManagerPeerProvider} is required to be implemented by
* the currently used {@link java.awt.Toolkit} instance. In order to initialize
* {@link java.awt.KeyboardFocusManager}, a singleton instance of {@link KeyboardFocusManagerPeer}
* is needed. To obtain that instance, the {@link #getKeyboardFocusManagerPeer}
* method of the current toolkit is called.
*/
public interface KeyboardFocusManagerPeerProvider {
/**
* Gets a singleton KeyboardFocusManagerPeer instance.
*/
KeyboardFocusManagerPeer getKeyboardFocusManagerPeer();
}

View File

@@ -0,0 +1,203 @@
/*
* Copyright (c) 2013, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.Component;
import java.awt.Container;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MenuBar;
import java.awt.MenuComponent;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragGestureRecognizer;
import java.awt.dnd.DragSource;
import java.awt.dnd.DropTarget;
import java.awt.dnd.InvalidDnDOperationException;
import java.awt.dnd.peer.DragSourceContextPeer;
import java.awt.peer.FramePeer;
/**
* The class provides basic functionality for a lightweight frame
* implementation. A subclass is expected to provide painting to an
* offscreen image and access to it. Thus it can be used for lightweight
* embedding.
*
* @author Artem Ananiev
* @author Anton Tarasov
*/
@SuppressWarnings("serial")
public abstract class LightweightFrame extends Frame {
/**
* Constructs a new, initially invisible {@code LightweightFrame}
* instance.
*/
public LightweightFrame() {
setUndecorated(true);
setResizable(true);
setEnabled(true);
}
/**
* Blocks introspection of a parent window by this child.
*
* @return null
*/
@Override public final Container getParent() { return null; }
@Override public Graphics getGraphics() { return null; }
@Override public final boolean isResizable() { return true; }
// Block modification of any frame attributes, since they aren't
// applicable for a lightweight frame.
@Override public final void setTitle(String title) {}
@Override public final void setIconImage(Image image) {}
@Override public final void setIconImages(java.util.List<? extends Image> icons) {}
@Override public final void setMenuBar(MenuBar mb) {}
@Override public final void setResizable(boolean resizable) {}
@Override public final void remove(MenuComponent m) {}
@Override public final void toFront() {}
@Override public final void toBack() {}
@Override public void addNotify() {
synchronized (getTreeLock()) {
if (getPeer() == null) {
SunToolkit stk = (SunToolkit)Toolkit.getDefaultToolkit();
try {
setPeer(stk.createLightweightFrame(this));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
super.addNotify();
}
}
private void setPeer(final FramePeer p) {
AWTAccessor.getComponentAccessor().setPeer(this, p);
}
/**
* Requests the peer to emulate activation or deactivation of the
* frame. Peers should override this method if they are to implement
* this functionality.
*
* @param activate if <code>true</code>, activates the frame;
* otherwise, deactivates the frame
*/
public void emulateActivation(boolean activate) {
((FramePeer)getPeer()).emulateActivation(activate);
}
/**
* Delegates the focus grab action to the client (embedding) application.
* The method is called by the AWT grab machinery.
*
* @see SunToolkit#grab(java.awt.Window)
*/
public abstract void grabFocus();
/**
* Delegates the focus ungrab action to the client (embedding) application.
* The method is called by the AWT grab machinery.
*
* @see SunToolkit#ungrab(java.awt.Window)
*/
public abstract void ungrabFocus();
/**
* Returns the scale factor of this frame. The default value is 1.
*
* @return the scale factor
* @see #notifyDisplayChanged(int)
*/
public abstract int getScaleFactor();
/**
* Called when display of the hosted frame is changed.
*
* @param scaleFactor the scale factor
*/
public abstract void notifyDisplayChanged(int scaleFactor);
/**
* Host window absolute bounds.
*/
private int hostX, hostY, hostW, hostH;
/**
* Returns the absolute bounds of the host (embedding) window.
*
* @return the host window bounds
*/
public Rectangle getHostBounds() {
if (hostX == 0 && hostY == 0 && hostW == 0 && hostH == 0) {
// The client app is probably unaware of the setHostBounds.
// A safe fall-back:
return getBounds();
}
return new Rectangle(hostX, hostY, hostW, hostH);
}
/**
* Sets the absolute bounds of the host (embedding) window.
*/
public void setHostBounds(int x, int y, int w, int h) {
hostX = x;
hostY = y;
hostW = w;
hostH = h;
}
/**
* Create a drag gesture recognizer for the lightweight frame.
*/
public abstract <T extends DragGestureRecognizer> T createDragGestureRecognizer(
Class<T> abstractRecognizerClass,
DragSource ds, Component c, int srcActions,
DragGestureListener dgl);
/**
* Create a drag source context peer for the lightweight frame.
*/
public abstract DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException;
/**
* Adds a drop target to the lightweight frame.
*/
public abstract void addDropTarget(DropTarget dt);
/**
* Removes a drop target from the lightweight frame.
*/
public abstract void removeDropTarget(DropTarget dt);
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (c) 2003, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
/**
* Interface for identifying a component that will be excluded during
* modal operations. Implementing this interface will ensure that the
* component willl still receive it's events.
*
* @since 1.5
* @author Joshua Outwater
*/
public interface ModalExclude {
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 2003, 2011, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.*;
/**
* Event object describing changes in AWT modality
*/
@SuppressWarnings("serial")
public class ModalityEvent extends AWTEvent implements ActiveEvent {
public static final int MODALITY_PUSHED = 1300;
public static final int MODALITY_POPPED = 1301;
private ModalityListener listener;
public ModalityEvent(Object source, ModalityListener listener, int id) {
super(source, id);
this.listener = listener;
}
public void dispatch() {
switch(getID()) {
case MODALITY_PUSHED:
listener.modalityPushed(this);
break;
case MODALITY_POPPED:
listener.modalityPopped(this);
break;
default:
throw new Error("Invalid event id.");
}
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2003, 2005, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
/**
* Listener interface so Java Plug-in can be notified
* of changes in AWT modality
*/
public interface ModalityListener {
/**
* Called by AWT when it enters a new level of modality
*/
public void modalityPushed(ModalityEvent ev);
/**
* Called by AWT when it exits a level of modality
*/
public void modalityPopped(ModalityEvent ev);
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 1999, 2000, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
public class Mutex {
private boolean locked;
private Thread owner;
public synchronized void lock() {
if (locked && Thread.currentThread() == owner) {
throw new IllegalMonitorStateException();
}
do {
if (!locked) {
locked = true;
owner = Thread.currentThread();
} else {
try {
wait();
} catch (InterruptedException e) {
// try again
}
}
} while (owner != Thread.currentThread());
}
public synchronized void unlock() {
if (Thread.currentThread() != owner) {
throw new IllegalMonitorStateException();
}
owner = null;
locked = false;
notify();
}
protected boolean isOwned() {
return (locked && Thread.currentThread() == owner);
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 1998, 2012, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
class NativeLibLoader {
/**
* This is copied from java.awt.Toolkit since we need the library
* loaded in sun.awt.image also:
*
* WARNING: This is a temporary workaround for a problem in the
* way the AWT loads native libraries. A number of classes in this
* package (sun.awt.image) have a native method, initIDs(),
* which initializes
* the JNI field and method ids used in the native portion of
* their implementation.
*
* Since the use and storage of these ids is done by the
* implementation libraries, the implementation of these method is
* provided by the particular AWT implementations
* (i.e. "Toolkit"s/Peer), such as Motif, Win32 or Tiny. The
* problem is that this means that the native libraries must be
* loaded by the java.* classes, which do not necessarily know the
* names of the libraries to load. A better way of doing this
* would be to provide a separate library which defines java.awt.*
* initIDs, and exports the relevant symbols out to the
* implementation libraries.
*
* For now, we know it's done by the implementation, and we assume
* that the name of the library is "awt". -br.
*/
static void loadLibraries() {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
public Void run() {
System.loadLibrary("awt");
return null;
}
});
}
}

View File

@@ -0,0 +1,308 @@
/*
* Copyright (c) 2000, 2013, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.AWTException;
import java.awt.BufferCapabilities;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.Insets;
import java.awt.MenuBar;
import java.awt.Point;
import java.awt.Event;
import java.awt.event.PaintEvent;
import java.awt.image.ColorModel;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.VolatileImage;
import java.awt.peer.CanvasPeer;
import java.awt.peer.LightweightPeer;
import java.awt.peer.PanelPeer;
import java.awt.peer.ComponentPeer;
import java.awt.peer.ContainerPeer;
import java.awt.Rectangle;
import sun.java2d.pipe.Region;
/**
* Implements the LightweightPeer interface for use in lightweight components
* that have no native window associated with them. This gets created by
* default in Component so that Component and Container can be directly
* extended to create useful components written entirely in java. These
* components must be hosted somewhere higher up in the component tree by a
* native container (such as a Frame).
*
* This implementation provides no useful semantics and serves only as a
* marker. One could provide alternative implementations in java that do
* something useful for some of the other peer interfaces to minimize the
* native code.
*
* This was renamed from java.awt.LightweightPeer (a horrible and confusing
* name) and moved from java.awt.Toolkit into sun.awt as a public class in
* its own file.
*
* @author Timothy Prinzing
* @author Michael Martak
*/
public class NullComponentPeer implements LightweightPeer,
CanvasPeer, PanelPeer {
public boolean isObscured() {
return false;
}
public boolean canDetermineObscurity() {
return false;
}
public boolean isFocusable() {
return false;
}
public void setVisible(boolean b) {
}
public void show() {
}
public void hide() {
}
public void setEnabled(boolean b) {
}
public void enable() {
}
public void disable() {
}
public void paint(Graphics g) {
}
public void repaint(long tm, int x, int y, int width, int height) {
}
public void print(Graphics g) {
}
public void setBounds(int x, int y, int width, int height, int op) {
}
public void reshape(int x, int y, int width, int height) {
}
public void coalescePaintEvent(PaintEvent e) {
}
public boolean handleEvent(Event e) {
return false;
}
public void handleEvent(java.awt.AWTEvent arg0) {
}
public Dimension getPreferredSize() {
return new Dimension(1,1);
}
public Dimension getMinimumSize() {
return new Dimension(1,1);
}
public ColorModel getColorModel() {
return null;
}
public Graphics getGraphics() {
return null;
}
public GraphicsConfiguration getGraphicsConfiguration() {
return null;
}
public FontMetrics getFontMetrics(Font font) {
return null;
}
public void dispose() {
// no native code
}
public void setForeground(Color c) {
}
public void setBackground(Color c) {
}
public void setFont(Font f) {
}
public void updateCursorImmediately() {
}
public void setCursor(Cursor cursor) {
}
public boolean requestFocus
(Component lightweightChild, boolean temporary,
boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause) {
return false;
}
public Image createImage(ImageProducer producer) {
return null;
}
public Image createImage(int width, int height) {
return null;
}
public boolean prepareImage(Image img, int w, int h, ImageObserver o) {
return false;
}
public int checkImage(Image img, int w, int h, ImageObserver o) {
return 0;
}
public Dimension preferredSize() {
return getPreferredSize();
}
public Dimension minimumSize() {
return getMinimumSize();
}
public Point getLocationOnScreen() {
return new Point(0,0);
}
public Insets getInsets() {
return insets();
}
public void beginValidate() {
}
public void endValidate() {
}
public Insets insets() {
return new Insets(0, 0, 0, 0);
}
public boolean isPaintPending() {
return false;
}
public boolean handlesWheelScrolling() {
return false;
}
public VolatileImage createVolatileImage(int width, int height) {
return null;
}
public void beginLayout() {
}
public void endLayout() {
}
public void createBuffers(int numBuffers, BufferCapabilities caps)
throws AWTException {
throw new AWTException(
"Page-flipping is not allowed on a lightweight component");
}
public Image getBackBuffer() {
throw new IllegalStateException(
"Page-flipping is not allowed on a lightweight component");
}
public void flip(int x1, int y1, int x2, int y2,
BufferCapabilities.FlipContents flipAction)
{
throw new IllegalStateException(
"Page-flipping is not allowed on a lightweight component");
}
public void destroyBuffers() {
}
/**
* @see java.awt.peer.ComponentPeer#isReparentSupported
*/
public boolean isReparentSupported() {
return false;
}
/**
* @see java.awt.peer.ComponentPeer#reparent
*/
public void reparent(ContainerPeer newNativeParent) {
throw new UnsupportedOperationException();
}
public void layout() {
}
public Rectangle getBounds() {
return new Rectangle(0, 0, 0, 0);
}
/**
* Applies the shape to the native component window.
* @since 1.7
*/
public void applyShape(Region shape) {
}
/**
* Lowers this component at the bottom of the above HW peer. If the above parameter
* is null then the method places this component at the top of the Z-order.
*/
public void setZOrder(ComponentPeer above) {
}
public boolean updateGraphicsData(GraphicsConfiguration gc) {
return false;
}
public GraphicsConfiguration getAppropriateGraphicsConfiguration(
GraphicsConfiguration gc)
{
return gc;
}
}

View File

@@ -0,0 +1,189 @@
/*
* Copyright (c) 1997, 2012, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Map;
import static sun.awt.OSInfo.OSType.*;
/**
* @author Pavel Porvatov
*/
public class OSInfo {
public static enum OSType {
WINDOWS,
LINUX,
SOLARIS,
MACOSX,
UNKNOWN
}
/*
The map windowsVersionMap must contain all windows version constants except WINDOWS_UNKNOWN,
and so the method getWindowsVersion() will return the constant for known OS.
It allows compare objects by "==" instead of "equals".
*/
public static final WindowsVersion WINDOWS_UNKNOWN = new WindowsVersion(-1, -1);
public static final WindowsVersion WINDOWS_95 = new WindowsVersion(4, 0);
public static final WindowsVersion WINDOWS_98 = new WindowsVersion(4, 10);
public static final WindowsVersion WINDOWS_ME = new WindowsVersion(4, 90);
public static final WindowsVersion WINDOWS_2000 = new WindowsVersion(5, 0);
public static final WindowsVersion WINDOWS_XP = new WindowsVersion(5, 1);
public static final WindowsVersion WINDOWS_2003 = new WindowsVersion(5, 2);
public static final WindowsVersion WINDOWS_VISTA = new WindowsVersion(6, 0);
private static final String OS_NAME = "os.name";
private static final String OS_VERSION = "os.version";
private final static Map<String, WindowsVersion> windowsVersionMap = new HashMap<String, OSInfo.WindowsVersion>();
static {
windowsVersionMap.put(WINDOWS_95.toString(), WINDOWS_95);
windowsVersionMap.put(WINDOWS_98.toString(), WINDOWS_98);
windowsVersionMap.put(WINDOWS_ME.toString(), WINDOWS_ME);
windowsVersionMap.put(WINDOWS_2000.toString(), WINDOWS_2000);
windowsVersionMap.put(WINDOWS_XP.toString(), WINDOWS_XP);
windowsVersionMap.put(WINDOWS_2003.toString(), WINDOWS_2003);
windowsVersionMap.put(WINDOWS_VISTA.toString(), WINDOWS_VISTA);
}
private static final PrivilegedAction<OSType> osTypeAction = new PrivilegedAction<OSType>() {
public OSType run() {
return getOSType();
}
};
private OSInfo() {
// Don't allow to create instances
}
/**
* Returns type of operating system.
*/
public static OSType getOSType() throws SecurityException {
String osName = System.getProperty(OS_NAME);
if (osName != null) {
if (osName.contains("Windows")) {
return WINDOWS;
}
if (osName.contains("Linux")) {
return LINUX;
}
if (osName.contains("Solaris") || osName.contains("SunOS")) {
return SOLARIS;
}
if (osName.contains("OS X")) {
return MACOSX;
}
// determine another OS here
}
return UNKNOWN;
}
public static PrivilegedAction<OSType> getOSTypeAction() {
return osTypeAction;
}
public static WindowsVersion getWindowsVersion() throws SecurityException {
String osVersion = System.getProperty(OS_VERSION);
if (osVersion == null) {
return WINDOWS_UNKNOWN;
}
synchronized (windowsVersionMap) {
WindowsVersion result = windowsVersionMap.get(osVersion);
if (result == null) {
// Try parse version and put object into windowsVersionMap
String[] arr = osVersion.split("\\.");
if (arr.length == 2) {
try {
result = new WindowsVersion(Integer.parseInt(arr[0]), Integer.parseInt(arr[1]));
} catch (NumberFormatException e) {
return WINDOWS_UNKNOWN;
}
} else {
return WINDOWS_UNKNOWN;
}
windowsVersionMap.put(osVersion, result);
}
return result;
}
}
public static class WindowsVersion implements Comparable<WindowsVersion> {
private final int major;
private final int minor;
private WindowsVersion(int major, int minor) {
this.major = major;
this.minor = minor;
}
public int getMajor() {
return major;
}
public int getMinor() {
return minor;
}
public int compareTo(WindowsVersion o) {
int result = major - o.getMajor();
if (result == 0) {
result = minor - o.getMinor();
}
return result;
}
public boolean equals(Object obj) {
return obj instanceof WindowsVersion && compareTo((WindowsVersion) obj) == 0;
}
public int hashCode() {
return 31 * major + minor;
}
public String toString() {
return major + "." + minor;
}
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (c) 2018, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
/**
* Used for replacing window owner with another non-Swing window.
* It is useful in case of JavaFX-Swing interop:
* it helps to keep Swing dialogs above its owner(JavaFX stage).
*/
public interface OverrideNativeWindowHandle {
/**
* Replaces an owner window with a window with provided handle.
* @param handle native window handle
*/
void overrideWindowHandle(final long handle);
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright (c) 2005, 2011, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.Component;
import java.awt.Rectangle;
import java.awt.event.PaintEvent;
/**
* PaintEventDispatcher is responsible for dispatching PaintEvents. There
* can be only one PaintEventDispatcher active at a particular time.
*
*/
public class PaintEventDispatcher {
/**
* Singleton dispatcher.
*/
private static PaintEventDispatcher dispatcher;
/**
* Sets the current <code>PaintEventDispatcher</code>.
*
* @param dispatcher PaintEventDispatcher
*/
public static void setPaintEventDispatcher(
PaintEventDispatcher dispatcher) {
synchronized(PaintEventDispatcher.class) {
PaintEventDispatcher.dispatcher = dispatcher;
}
}
/**
* Returns the currently active <code>PaintEventDispatcher</code>. This
* will never return null.
*
* @return PaintEventDispatcher
*/
public static PaintEventDispatcher getPaintEventDispatcher() {
synchronized(PaintEventDispatcher.class) {
if (dispatcher == null) {
dispatcher = new PaintEventDispatcher();
}
return dispatcher;
}
}
/**
* Creates and returns the <code>PaintEvent</code> that should be
* dispatched for the specified component. If this returns null
* no <code>PaintEvent</code> is dispatched.
* <p>
* <b>WARNING:</b> This is invoked from the native thread, be careful
* what methods you end up invoking here.
*/
public PaintEvent createPaintEvent(Component target, int x, int y, int w,
int h) {
return new PaintEvent(target, PaintEvent.PAINT,
new Rectangle(x, y, w, h));
}
/**
* Returns true if a native background erase should be done for
* the specified Component.
*/
public boolean shouldDoNativeBackgroundErase(Component c) {
return true;
}
/**
* This method is invoked from the toolkit thread when the surface
* data of the component needs to be replaced. The method run() of
* the Runnable argument performs surface data replacing, run()
* should be invoked on the EDT of this component's AppContext.
* Returns true if the Runnable has been enqueued to be invoked
* on the EDT.
* (Fix 6255371.)
*/
public boolean queueSurfaceDataReplacing(Component c, Runnable r) {
return false;
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 1998, 2011, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.event.InvocationEvent;
@SuppressWarnings("serial")
public class PeerEvent extends InvocationEvent {
public static final long PRIORITY_EVENT = 0x01;
public static final long ULTIMATE_PRIORITY_EVENT = 0x02;
public static final long LOW_PRIORITY_EVENT = 0x04;
private long flags;
public PeerEvent(Object source, Runnable runnable, long flags) {
this(source, runnable, null, false, flags);
}
public PeerEvent(Object source, Runnable runnable, Object notifier,
boolean catchExceptions, long flags) {
super(source, runnable, notifier, catchExceptions);
this.flags = flags;
}
public long getFlags() {
return flags;
}
public PeerEvent coalesceEvents(PeerEvent newEvent) {
return null;
}
}

View File

@@ -0,0 +1,440 @@
/*
* Copyright (c) 1996, 2010, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.peer.FontPeer;
import java.util.Locale;
import java.util.Vector;
import sun.font.SunFontManager;
import sun.java2d.FontSupport;
import java.nio.CharBuffer;
import java.nio.ByteBuffer;
public abstract class PlatformFont implements FontPeer {
static {
NativeLibLoader.loadLibraries();
initIDs();
}
protected FontDescriptor[] componentFonts;
protected char defaultChar;
protected FontConfiguration fontConfig;
protected FontDescriptor defaultFont;
protected String familyName;
private Object[] fontCache;
// Maybe this should be a property that is set based
// on the locale?
protected static int FONTCACHESIZE = 256;
protected static int FONTCACHEMASK = PlatformFont.FONTCACHESIZE - 1;
protected static String osVersion;
public PlatformFont(String name, int style){
SunFontManager sfm = SunFontManager.getInstance();
if (sfm instanceof FontSupport) {
fontConfig = ((FontSupport)sfm).getFontConfiguration();
}
if (fontConfig == null) {
return;
}
// map given font name to a valid logical font family name
familyName = name.toLowerCase(Locale.ENGLISH);
if (!FontConfiguration.isLogicalFontFamilyName(familyName)) {
familyName = fontConfig.getFallbackFamilyName(familyName, "sansserif");
}
componentFonts = fontConfig.getFontDescriptors(familyName, style);
// search default character
//
char missingGlyphCharacter = getMissingGlyphCharacter();
defaultChar = '?';
if (componentFonts.length > 0)
defaultFont = componentFonts[0];
for (int i = 0; i < componentFonts.length; i++){
if (componentFonts[i].isExcluded(missingGlyphCharacter)) {
continue;
}
if (componentFonts[i].encoder.canEncode(missingGlyphCharacter)) {
defaultFont = componentFonts[i];
defaultChar = missingGlyphCharacter;
break;
}
}
}
/**
* Returns the character that should be rendered when a glyph
* is missing.
*/
protected abstract char getMissingGlyphCharacter();
/**
* make a array of CharsetString with given String.
*/
public CharsetString[] makeMultiCharsetString(String str){
return makeMultiCharsetString(str.toCharArray(), 0, str.length(), true);
}
/**
* make a array of CharsetString with given String.
*/
public CharsetString[] makeMultiCharsetString(String str, boolean allowdefault){
return makeMultiCharsetString(str.toCharArray(), 0, str.length(), allowdefault);
}
/**
* make a array of CharsetString with given char array.
* @param str The char array to convert.
* @param offset offset of first character of interest
* @param len number of characters to convert
*/
public CharsetString[] makeMultiCharsetString(char str[], int offset, int len) {
return makeMultiCharsetString(str, offset, len, true);
}
/**
* make a array of CharsetString with given char array.
* @param str The char array to convert.
* @param offset offset of first character of interest
* @param len number of characters to convert
* @param allowDefault whether to allow the default char.
* Setting this to true overloads the meaning of this method to
* return non-null only if all chars can be converted.
* @return array of CharsetString or if allowDefault is false and any
* of the returned chars would have been converted to a default char,
* then return null.
* This is used to choose alternative means of displaying the text.
*/
public CharsetString[] makeMultiCharsetString(char str[], int offset, int len,
boolean allowDefault) {
if (len < 1) {
return new CharsetString[0];
}
Vector mcs = null;
char[] tmpStr = new char[len];
char tmpChar = defaultChar;
boolean encoded = false;
FontDescriptor currentFont = defaultFont;
for (int i = 0; i < componentFonts.length; i++) {
if (componentFonts[i].isExcluded(str[offset])){
continue;
}
/* Need "encoded" variable to distinguish the case when
* the default char is the same as the encoded char.
* The defaultChar on Linux is '?' so it is needed there.
*/
if (componentFonts[i].encoder.canEncode(str[offset])){
currentFont = componentFonts[i];
tmpChar = str[offset];
encoded = true;
break;
}
}
if (!allowDefault && !encoded) {
return null;
} else {
tmpStr[0] = tmpChar;
}
int lastIndex = 0;
for (int i = 1; i < len; i++){
char ch = str[offset + i];
FontDescriptor fd = defaultFont;
tmpChar = defaultChar;
encoded = false;
for (int j = 0; j < componentFonts.length; j++){
if (componentFonts[j].isExcluded(ch)){
continue;
}
if (componentFonts[j].encoder.canEncode(ch)){
fd = componentFonts[j];
tmpChar = ch;
encoded = true;
break;
}
}
if (!allowDefault && !encoded) {
return null;
} else {
tmpStr[i] = tmpChar;
}
if (currentFont != fd){
if (mcs == null) {
mcs = new Vector(3);
}
mcs.addElement(new CharsetString(tmpStr, lastIndex,
i-lastIndex, currentFont));
currentFont = fd;
fd = defaultFont;
lastIndex = i;
}
}
CharsetString[] result;
CharsetString cs = new CharsetString(tmpStr, lastIndex,
len-lastIndex, currentFont);
if (mcs == null) {
result = new CharsetString[1];
result[0] = cs;
} else {
mcs.addElement(cs);
result = new CharsetString[mcs.size()];
for (int i = 0; i < mcs.size(); i++){
result[i] = (CharsetString)mcs.elementAt(i);
}
}
return result;
}
/**
* Is it possible that this font's metrics require the multi-font calls?
* This might be true, for example, if the font supports kerning.
**/
public boolean mightHaveMultiFontMetrics() {
return fontConfig != null;
}
/**
* Specialized fast path string conversion for AWT.
*/
public Object[] makeConvertedMultiFontString(String str)
{
return makeConvertedMultiFontChars(str.toCharArray(),0,str.length());
}
public Object[] makeConvertedMultiFontChars(char[] data,
int start, int len)
{
Object[] result = new Object[2];
Object[] workingCache;
byte[] convertedData = null;
int stringIndex = start;
int convertedDataIndex = 0;
int resultIndex = 0;
int cacheIndex;
FontDescriptor currentFontDescriptor = null;
FontDescriptor lastFontDescriptor = null;
char currentDefaultChar;
PlatformFontCache theChar;
// Simple bounds check
int end = start + len;
if (start < 0 || end > data.length) {
throw new ArrayIndexOutOfBoundsException();
}
if(stringIndex >= end) {
return null;
}
// coversion loop
while(stringIndex < end)
{
currentDefaultChar = data[stringIndex];
// Note that cache sizes must be a power of two!
cacheIndex = (int)(currentDefaultChar & this.FONTCACHEMASK);
theChar = (PlatformFontCache)getFontCache()[cacheIndex];
// Is the unicode char we want cached?
if(theChar == null || theChar.uniChar != currentDefaultChar)
{
/* find a converter that can convert the current character */
currentFontDescriptor = defaultFont;
currentDefaultChar = defaultChar;
char ch = (char)data[stringIndex];
int componentCount = componentFonts.length;
for (int j = 0; j < componentCount; j++) {
FontDescriptor fontDescriptor = componentFonts[j];
fontDescriptor.encoder.reset();
//fontDescriptor.encoder.onUnmappleCharacterAction(...);
if (fontDescriptor.isExcluded(ch)) {
continue;
}
if (fontDescriptor.encoder.canEncode(ch)) {
currentFontDescriptor = fontDescriptor;
currentDefaultChar = ch;
break;
}
}
try {
char[] input = new char[1];
input[0] = currentDefaultChar;
theChar = new PlatformFontCache();
if (currentFontDescriptor.useUnicode()) {
/*
currentFontDescriptor.unicodeEncoder.encode(CharBuffer.wrap(input),
theChar.bb,
true);
*/
if (currentFontDescriptor.isLE) {
theChar.bb.put((byte)(input[0] & 0xff));
theChar.bb.put((byte)(input[0] >>8));
} else {
theChar.bb.put((byte)(input[0] >> 8));
theChar.bb.put((byte)(input[0] & 0xff));
}
}
else {
currentFontDescriptor.encoder.encode(CharBuffer.wrap(input),
theChar.bb,
true);
}
theChar.fontDescriptor = currentFontDescriptor;
theChar.uniChar = data[stringIndex];
getFontCache()[cacheIndex] = theChar;
} catch(Exception e){
// Should never happen!
System.err.println(e);
e.printStackTrace();
return null;
}
}
// Check to see if we've changed fonts.
if(lastFontDescriptor != theChar.fontDescriptor) {
if(lastFontDescriptor != null) {
result[resultIndex++] = lastFontDescriptor;
result[resultIndex++] = convertedData;
// Add the size to the converted data field.
if(convertedData != null) {
convertedDataIndex -= 4;
convertedData[0] = (byte)(convertedDataIndex >> 24);
convertedData[1] = (byte)(convertedDataIndex >> 16);
convertedData[2] = (byte)(convertedDataIndex >> 8);
convertedData[3] = (byte)convertedDataIndex;
}
if(resultIndex >= result.length) {
Object[] newResult = new Object[result.length * 2];
System.arraycopy(result, 0, newResult, 0,
result.length);
result = newResult;
}
}
if (theChar.fontDescriptor.useUnicode()) {
convertedData = new byte[(end - stringIndex + 1) *
(int)theChar.fontDescriptor.unicodeEncoder.maxBytesPerChar()
+ 4];
}
else {
convertedData = new byte[(end - stringIndex + 1) *
(int)theChar.fontDescriptor.encoder.maxBytesPerChar()
+ 4];
}
convertedDataIndex = 4;
lastFontDescriptor = theChar.fontDescriptor;
}
byte[] ba = theChar.bb.array();
int size = theChar.bb.position();
if(size == 1) {
convertedData[convertedDataIndex++] = ba[0];
}
else if(size == 2) {
convertedData[convertedDataIndex++] = ba[0];
convertedData[convertedDataIndex++] = ba[1];
} else if(size == 3) {
convertedData[convertedDataIndex++] = ba[0];
convertedData[convertedDataIndex++] = ba[1];
convertedData[convertedDataIndex++] = ba[2];
} else if(size == 4) {
convertedData[convertedDataIndex++] = ba[0];
convertedData[convertedDataIndex++] = ba[1];
convertedData[convertedDataIndex++] = ba[2];
convertedData[convertedDataIndex++] = ba[3];
}
stringIndex++;
}
result[resultIndex++] = lastFontDescriptor;
result[resultIndex] = convertedData;
// Add the size to the converted data field.
if(convertedData != null) {
convertedDataIndex -= 4;
convertedData[0] = (byte)(convertedDataIndex >> 24);
convertedData[1] = (byte)(convertedDataIndex >> 16);
convertedData[2] = (byte)(convertedDataIndex >> 8);
convertedData[3] = (byte)convertedDataIndex;
}
return result;
}
/*
* Create fontCache on demand instead of during construction to
* reduce overall memory consumption.
*
* This method is declared final so that its code can be inlined
* by the compiler.
*/
protected final Object[] getFontCache() {
// This method is not MT-safe by design. Since this is just a
// cache anyways, it's okay if we occasionally allocate the array
// twice or return an array which will be dereferenced and gced
// right away.
if (fontCache == null) {
fontCache = new Object[this.FONTCACHESIZE];
}
return fontCache;
}
/**
* Initialize JNI field and method IDs
*/
private static native void initIDs();
class PlatformFontCache
{
char uniChar;
FontDescriptor fontDescriptor;
ByteBuffer bb = ByteBuffer.allocate(4);
}
}

View File

@@ -0,0 +1,312 @@
/*
* Copyright (c) 1999, 2007, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.PaintEvent;
/**
* The <code>RepaintArea</code> is a geometric construct created for the
* purpose of holding the geometry of several coalesced paint events.
* This geometry is accessed synchronously, although it is written such
* that painting may still be executed asynchronously.
*
* @author Eric Hawkes
* @since 1.3
*/
public class RepaintArea {
/**
* Maximum ratio of bounding rectangle to benefit for which
* both the vertical and horizontal unions are repainted.
* For smaller ratios the whole bounding rectangle is repainted.
* @see #paint
*/
private static final int MAX_BENEFIT_RATIO = 4;
private static final int HORIZONTAL = 0;
private static final int VERTICAL = 1;
private static final int UPDATE = 2;
private static final int RECT_COUNT = UPDATE + 1;
private Rectangle paintRects[] = new Rectangle[RECT_COUNT];
/**
* Constructs a new <code>RepaintArea</code>
* @since 1.3
*/
public RepaintArea() {
}
/**
* Constructs a new <code>RepaintArea</code> initialized to match
* the values of the specified RepaintArea.
*
* @param ra the <code>RepaintArea</code> from which to copy initial
* values to a newly constructed RepaintArea
* @since 1.3
*/
private RepaintArea(RepaintArea ra) {
// This constructor is private because it should only be called
// from the cloneAndReset method
for (int i = 0; i < RECT_COUNT; i++) {
paintRects[i] = ra.paintRects[i];
}
}
/**
* Adds a <code>Rectangle</code> to this <code>RepaintArea</code>.
* PAINT Rectangles are divided into mostly vertical and mostly horizontal.
* Each group is unioned together.
* UPDATE Rectangles are unioned.
*
* @param r the specified <code>Rectangle</code>
* @param id possible values PaintEvent.UPDATE or PaintEvent.PAINT
* @since 1.3
*/
public synchronized void add(Rectangle r, int id) {
// Make sure this new rectangle has positive dimensions
if (r.isEmpty()) {
return;
}
int addTo = UPDATE;
if (id == PaintEvent.PAINT) {
addTo = (r.width > r.height) ? HORIZONTAL : VERTICAL;
}
if (paintRects[addTo] != null) {
paintRects[addTo].add(r);
} else {
paintRects[addTo] = new Rectangle(r);
}
}
/**
* Creates a new <code>RepaintArea</code> with the same geometry as this
* RepaintArea, then removes all of the geometry from this
* RepaintArea and restores it to an empty RepaintArea.
*
* @return ra a new <code>RepaintArea</code> having the same geometry as
* this RepaintArea.
* @since 1.3
*/
private synchronized RepaintArea cloneAndReset() {
RepaintArea ra = new RepaintArea(this);
for (int i = 0; i < RECT_COUNT; i++) {
paintRects[i] = null;
}
return ra;
}
public boolean isEmpty() {
for (int i = 0; i < RECT_COUNT; i++) {
if (paintRects[i] != null) {
return false;
}
}
return true;
}
/**
* Constrains the size of the repaint area to the passed in bounds.
*/
public synchronized void constrain(int x, int y, int w, int h) {
for (int i = 0; i < RECT_COUNT; i++) {
Rectangle rect = paintRects[i];
if (rect != null) {
if (rect.x < x) {
rect.width -= (x - rect.x);
rect.x = x;
}
if (rect.y < y) {
rect.height -= (y - rect.y);
rect.y = y;
}
int xDelta = rect.x + rect.width - x - w;
if (xDelta > 0) {
rect.width -= xDelta;
}
int yDelta = rect.y + rect.height - y - h;
if (yDelta > 0) {
rect.height -= yDelta;
}
if (rect.width <= 0 || rect.height <= 0) {
paintRects[i] = null;
}
}
}
}
/**
* Marks the passed in region as not needing to be painted. It's possible
* this will do nothing.
*/
public synchronized void subtract(int x, int y, int w, int h) {
Rectangle subtract = new Rectangle(x, y, w, h);
for (int i = 0; i < RECT_COUNT; i++) {
if (subtract(paintRects[i], subtract)) {
if (paintRects[i] != null && paintRects[i].isEmpty()) {
paintRects[i] = null;
}
}
}
}
/**
* Invokes paint and update on target Component with optimal
* rectangular clip region.
* If PAINT bounding rectangle is less than
* MAX_BENEFIT_RATIO times the benefit, then the vertical and horizontal unions are
* painted separately. Otherwise the entire bounding rectangle is painted.
*
* @param target Component to <code>paint</code> or <code>update</code>
* @since 1.4
*/
public void paint(Object target, boolean shouldClearRectBeforePaint) {
Component comp = (Component)target;
if (isEmpty()) {
return;
}
if (!comp.isVisible()) {
return;
}
RepaintArea ra = this.cloneAndReset();
if (!subtract(ra.paintRects[VERTICAL], ra.paintRects[HORIZONTAL])) {
subtract(ra.paintRects[HORIZONTAL], ra.paintRects[VERTICAL]);
}
if (ra.paintRects[HORIZONTAL] != null && ra.paintRects[VERTICAL] != null) {
Rectangle paintRect = ra.paintRects[HORIZONTAL].union(ra.paintRects[VERTICAL]);
int square = paintRect.width * paintRect.height;
int benefit = square - ra.paintRects[HORIZONTAL].width
* ra.paintRects[HORIZONTAL].height - ra.paintRects[VERTICAL].width
* ra.paintRects[VERTICAL].height;
// if benefit is comparable with bounding box
if (MAX_BENEFIT_RATIO * benefit < square) {
ra.paintRects[HORIZONTAL] = paintRect;
ra.paintRects[VERTICAL] = null;
}
}
for (int i = 0; i < paintRects.length; i++) {
if (ra.paintRects[i] != null
&& !ra.paintRects[i].isEmpty())
{
// Should use separate Graphics for each paint() call,
// since paint() can change Graphics state for next call.
Graphics g = comp.getGraphics();
if (g != null) {
try {
g.setClip(ra.paintRects[i]);
if (i == UPDATE) {
updateComponent(comp, g);
} else {
if (shouldClearRectBeforePaint) {
g.clearRect( ra.paintRects[i].x,
ra.paintRects[i].y,
ra.paintRects[i].width,
ra.paintRects[i].height);
}
paintComponent(comp, g);
}
} finally {
g.dispose();
}
}
}
}
}
/**
* Calls <code>Component.update(Graphics)</code> with given Graphics.
*/
protected void updateComponent(Component comp, Graphics g) {
if (comp != null) {
comp.update(g);
}
}
/**
* Calls <code>Component.paint(Graphics)</code> with given Graphics.
*/
protected void paintComponent(Component comp, Graphics g) {
if (comp != null) {
comp.paint(g);
}
}
/**
* Subtracts subtr from rect. If the result is rectangle
* changes rect and returns true. Otherwise false.
*/
static boolean subtract(Rectangle rect, Rectangle subtr) {
if (rect == null || subtr == null) {
return true;
}
Rectangle common = rect.intersection(subtr);
if (common.isEmpty()) {
return true;
}
if (rect.x == common.x && rect.y == common.y) {
if (rect.width == common.width) {
rect.y += common.height;
rect.height -= common.height;
return true;
} else
if (rect.height == common.height) {
rect.x += common.width;
rect.width -= common.width;
return true;
}
} else
if (rect.x + rect.width == common.x + common.width
&& rect.y + rect.height == common.y + common.height)
{
if (rect.width == common.width) {
rect.height -= common.height;
return true;
} else
if (rect.height == common.height) {
rect.width -= common.width;
return true;
}
}
return false;
}
public String toString() {
return super.toString() + "[ horizontal=" + paintRects[0] +
" vertical=" + paintRects[1] +
" update=" + paintRects[2] + "]";
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2006, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.Component;
public interface RequestFocusController
{
public boolean acceptRequestFocus(Component from, Component to,
boolean temporary, boolean focusedWindowChangeAllowed,
CausedFocusEvent.Cause cause);
}

View File

@@ -0,0 +1,187 @@
/*
* Copyright (c) 2000, 2013, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.ScrollPane;
import java.awt.Insets;
import java.awt.Adjustable;
import java.awt.event.MouseWheelEvent;
import sun.util.logging.PlatformLogger;
/*
* ScrollPaneWheelScroller is a helper class for implmenenting mouse wheel
* scrolling on a java.awt.ScrollPane. It contains only static methods.
* No objects of this class may be instantiated, thus it is declared abstract.
*/
public abstract class ScrollPaneWheelScroller {
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.ScrollPaneWheelScroller");
private ScrollPaneWheelScroller() {}
/*
* Called from ScrollPane.processMouseWheelEvent()
*/
public static void handleWheelScrolling(ScrollPane sp, MouseWheelEvent e) {
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer("x = " + e.getX() + ", y = " + e.getY() + ", src is " + e.getSource());
}
int increment = 0;
if (sp != null && e.getScrollAmount() != 0) {
Adjustable adj = getAdjustableToScroll(sp);
if (adj != null) {
increment = getIncrementFromAdjustable(adj, e);
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer("increment from adjustable(" + adj.getClass() + ") : " + increment);
}
scrollAdjustable(adj, increment);
}
}
}
/*
* Given a ScrollPane, determine which Scrollbar should be scrolled by the
* mouse wheel, if any.
*/
public static Adjustable getAdjustableToScroll(ScrollPane sp) {
int policy = sp.getScrollbarDisplayPolicy();
// if policy is display always or never, use vert
if (policy == ScrollPane.SCROLLBARS_ALWAYS ||
policy == ScrollPane.SCROLLBARS_NEVER) {
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer("using vertical scrolling due to scrollbar policy");
}
return sp.getVAdjustable();
}
else {
Insets ins = sp.getInsets();
int vertScrollWidth = sp.getVScrollbarWidth();
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer("insets: l = " + ins.left + ", r = " + ins.right +
", t = " + ins.top + ", b = " + ins.bottom);
log.finer("vertScrollWidth = " + vertScrollWidth);
}
// Check if scrollbar is showing by examining insets of the
// ScrollPane
if (ins.right >= vertScrollWidth) {
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer("using vertical scrolling because scrollbar is present");
}
return sp.getVAdjustable();
}
else {
int horizScrollHeight = sp.getHScrollbarHeight();
if (ins.bottom >= horizScrollHeight) {
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer("using horiz scrolling because scrollbar is present");
}
return sp.getHAdjustable();
}
else {
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer("using NO scrollbar becsause neither is present");
}
return null;
}
}
}
}
/*
* Given the info in a MouseWheelEvent and an Adjustable to scroll, return
* the amount by which the Adjustable should be adjusted. This value may
* be positive or negative.
*/
public static int getIncrementFromAdjustable(Adjustable adj,
MouseWheelEvent e) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
if (adj == null) {
log.fine("Assertion (adj != null) failed");
}
}
int increment = 0;
if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) {
increment = e.getUnitsToScroll() * adj.getUnitIncrement();
}
else if (e.getScrollType() == MouseWheelEvent.WHEEL_BLOCK_SCROLL) {
increment = adj.getBlockIncrement() * e.getWheelRotation();
}
return increment;
}
/*
* Scroll the given Adjustable by the given amount. Checks the Adjustable's
* bounds and sets the new value to the Adjustable.
*/
public static void scrollAdjustable(Adjustable adj, int amount) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
if (adj == null) {
log.fine("Assertion (adj != null) failed");
}
if (amount == 0) {
log.fine("Assertion (amount != 0) failed");
}
}
int current = adj.getValue();
int upperLimit = adj.getMaximum() - adj.getVisibleAmount();
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer("doScrolling by " + amount);
}
if (amount > 0 && current < upperLimit) { // still some room to scroll
// down
if (current + amount < upperLimit) {
adj.setValue(current + amount);
return;
}
else {
adj.setValue(upperLimit);
return;
}
}
else if (amount < 0 && current > adj.getMinimum()) { // still some room
// to scroll up
if (current + amount > adj.getMinimum()) {
adj.setValue(current + amount);
return;
}
else {
adj.setValue(adj.getMinimum());
return;
}
}
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2005, 2008, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
/**
* Interface used by Swing to make copies from the Swing back buffer
* more optimal when using BufferStrategy; no need to copy the entire
* buffer when only a small sub-region has changed.
* @see javax.swing.BufferStrategyPaintManager
*
*/
public interface SubRegionShowable {
/**
* Shows the specific subregion.
*/
public void show(int x1, int y1, int x2, int y2);
/**
* Shows the specified region if the buffer is not lost and the dimensions
* of the back-buffer match those of the component.
*
* @return true if successful
*/
// NOTE: this is invoked by swing on the toolkit thread!
public boolean showIfNotLost(int x1, int y1, int x2, int y2);
}

View File

@@ -0,0 +1,186 @@
/*
* Copyright (c) 2000, 2013, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.IllegalComponentStateException;
import java.util.Collections;
import java.util.Iterator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import sun.util.logging.PlatformLogger;
/**
* This class is used to aid in keeping track of DisplayChangedListeners and
* notifying them when a display change has taken place. DisplayChangedListeners
* are notified when the display's bit depth is changed, or when a top-level
* window has been dragged onto another screen.
*
* It is safe for a DisplayChangedListener to be added while the list is being
* iterated.
*
* The displayChanged() call is propagated after some occurrence (either
* due to user action or some other application) causes the display mode
* (e.g., depth or resolution) to change. All heavyweight components need
* to know when this happens because they need to create new surfaceData
* objects based on the new depth.
*
* displayChanged() is also called on Windows when they are moved from one
* screen to another on a system equipped with multiple displays.
*/
public class SunDisplayChanger {
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.multiscreen.SunDisplayChanger");
// Create a new synchronized map with initial capacity of one listener.
// It is asserted that the most common case is to have one GraphicsDevice
// and one top-level Window.
private Map<DisplayChangedListener, Void> listeners =
Collections.synchronizedMap(new WeakHashMap<DisplayChangedListener, Void>(1));
public SunDisplayChanger() {}
/*
* Add a DisplayChangeListener to this SunDisplayChanger so that it is
* notified when the display is changed.
*/
public void add(DisplayChangedListener theListener) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
if (theListener == null) {
log.fine("Assertion (theListener != null) failed");
}
}
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer("Adding listener: " + theListener);
}
listeners.put(theListener, null);
}
/*
* Remove the given DisplayChangeListener from this SunDisplayChanger.
*/
public void remove(DisplayChangedListener theListener) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
if (theListener == null) {
log.fine("Assertion (theListener != null) failed");
}
}
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer("Removing listener: " + theListener);
}
listeners.remove(theListener);
}
/*
* Notify our list of DisplayChangedListeners that a display change has
* taken place by calling their displayChanged() methods.
*/
public void notifyListeners() {
if (log.isLoggable(PlatformLogger.Level.FINEST)) {
log.finest("notifyListeners");
}
// This method is implemented by making a clone of the set of listeners,
// and then iterating over the clone. This is because during the course
// of responding to a display change, it may be appropriate for a
// DisplayChangedListener to add or remove itself from a SunDisplayChanger.
// If the set itself were iterated over, rather than a clone, it is
// trivial to get a ConcurrentModificationException by having a
// DisplayChangedListener remove itself from its list.
// Because all display change handling is done on the event thread,
// synchronization provides no protection against modifying the listener
// list while in the middle of iterating over it. -bchristi 7/10/2001
Set<DisplayChangedListener> cloneSet;
synchronized(listeners) {
cloneSet = new HashSet<DisplayChangedListener>(listeners.keySet());
}
Iterator<DisplayChangedListener> itr = cloneSet.iterator();
while (itr.hasNext()) {
DisplayChangedListener current = itr.next();
try {
if (log.isLoggable(PlatformLogger.Level.FINEST)) {
log.finest("displayChanged for listener: " + current);
}
current.displayChanged();
} catch (IllegalComponentStateException e) {
// This DisplayChangeListener is no longer valid. Most
// likely, a top-level window was dispose()d, but its
// Java objects have not yet been garbage collected. In any
// case, we no longer need to track this listener, though we
// do need to remove it from the original list, not the clone.
listeners.remove(current);
}
}
}
/*
* Notify our list of DisplayChangedListeners that a palette change has
* taken place by calling their paletteChanged() methods.
*/
public void notifyPaletteChanged() {
if (log.isLoggable(PlatformLogger.Level.FINEST)) {
log.finest("notifyPaletteChanged");
}
// This method is implemented by making a clone of the set of listeners,
// and then iterating over the clone. This is because during the course
// of responding to a display change, it may be appropriate for a
// DisplayChangedListener to add or remove itself from a SunDisplayChanger.
// If the set itself were iterated over, rather than a clone, it is
// trivial to get a ConcurrentModificationException by having a
// DisplayChangedListener remove itself from its list.
// Because all display change handling is done on the event thread,
// synchronization provides no protection against modifying the listener
// list while in the middle of iterating over it. -bchristi 7/10/2001
Set<DisplayChangedListener> cloneSet;
synchronized (listeners) {
cloneSet = new HashSet<DisplayChangedListener>(listeners.keySet());
}
Iterator<DisplayChangedListener> itr = cloneSet.iterator();
while (itr.hasNext()) {
DisplayChangedListener current = itr.next();
try {
if (log.isLoggable(PlatformLogger.Level.FINEST)) {
log.finest("paletteChanged for listener: " + current);
}
current.paletteChanged();
} catch (IllegalComponentStateException e) {
// This DisplayChangeListener is no longer valid. Most
// likely, a top-level window was dispose()d, but its
// Java objects have not yet been garbage collected. In any
// case, we no longer need to track this listener, though we
// do need to remove it from the original list, not the clone.
listeners.remove(current);
}
}
}
}

View File

@@ -0,0 +1,159 @@
/*
* Copyright (c) 1999, 2013, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.*;
import sun.util.logging.PlatformLogger;
public abstract class SunGraphicsCallback {
public static final int HEAVYWEIGHTS = 0x1;
public static final int LIGHTWEIGHTS = 0x2;
public static final int TWO_PASSES = 0x4;
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.SunGraphicsCallback");
public abstract void run(Component comp, Graphics cg);
protected void constrainGraphics(Graphics g, Rectangle bounds) {
if (g instanceof ConstrainableGraphics) {
((ConstrainableGraphics)g).constrain(bounds.x, bounds.y, bounds.width, bounds.height);
} else {
g.translate(bounds.x, bounds.y);
}
g.clipRect(0, 0, bounds.width, bounds.height);
}
@SuppressWarnings("deprecation")
public final void runOneComponent(Component comp, Rectangle bounds,
Graphics g, Shape clip,
int weightFlags) {
if (comp == null || comp.getPeer() == null || !comp.isVisible()) {
return;
}
boolean lightweight = comp.isLightweight();
if ((lightweight && (weightFlags & LIGHTWEIGHTS) == 0) ||
(!lightweight && (weightFlags & HEAVYWEIGHTS) == 0)) {
return;
}
if (bounds == null) {
bounds = comp.getBounds();
}
if (clip == null || clip.intersects(bounds)) {
Graphics cg = g.create();
try {
constrainGraphics(cg, bounds);
cg.setFont(comp.getFont());
cg.setColor(comp.getForeground());
if (cg instanceof Graphics2D) {
((Graphics2D)cg).setBackground(comp.getBackground());
} else if (cg instanceof Graphics2Delegate) {
((Graphics2Delegate)cg).setBackground(
comp.getBackground());
}
run(comp, cg);
} finally {
cg.dispose();
}
}
}
public final void runComponents(Component[] comps, Graphics g,
int weightFlags) {
int ncomponents = comps.length;
Shape clip = g.getClip();
if (log.isLoggable(PlatformLogger.Level.FINER) && (clip != null)) {
Rectangle newrect = clip.getBounds();
log.finer("x = " + newrect.x + ", y = " + newrect.y +
", width = " + newrect.width +
", height = " + newrect.height);
}
// A seriously sad hack--
// Lightweight components always paint behind peered components,
// even if they are at the top of the Z order. We emulate this
// behavior by making two printing passes: the first for lightweights;
// the second for heavyweights.
//
// ToDo(dpm): Either build a list of heavyweights during the
// lightweight pass, or redesign the components array to keep
// lightweights and heavyweights separate.
if ((weightFlags & TWO_PASSES) != 0) {
for (int i = ncomponents - 1; i >= 0; i--) {
runOneComponent(comps[i], null, g, clip, LIGHTWEIGHTS);
}
for (int i = ncomponents - 1; i >= 0; i--) {
runOneComponent(comps[i], null, g, clip, HEAVYWEIGHTS);
}
} else {
for (int i = ncomponents - 1; i >= 0; i--) {
runOneComponent(comps[i], null, g, clip, weightFlags);
}
}
}
public static final class PaintHeavyweightComponentsCallback
extends SunGraphicsCallback
{
private static PaintHeavyweightComponentsCallback instance =
new PaintHeavyweightComponentsCallback();
private PaintHeavyweightComponentsCallback() {}
public void run(Component comp, Graphics cg) {
if (!comp.isLightweight()) {
comp.paintAll(cg);
} else if (comp instanceof Container) {
runComponents(((Container)comp).getComponents(), cg,
LIGHTWEIGHTS | HEAVYWEIGHTS);
}
}
public static PaintHeavyweightComponentsCallback getInstance() {
return instance;
}
}
public static final class PrintHeavyweightComponentsCallback
extends SunGraphicsCallback
{
private static PrintHeavyweightComponentsCallback instance =
new PrintHeavyweightComponentsCallback();
private PrintHeavyweightComponentsCallback() {}
public void run(Component comp, Graphics cg) {
if (!comp.isLightweight()) {
comp.printAll(cg);
} else if (comp instanceof Container) {
runComponents(((Container)comp).getComponents(), cg,
LIGHTWEIGHTS | HEAVYWEIGHTS);
}
}
public static PrintHeavyweightComponentsCallback getInstance() {
return instance;
}
}
}

View File

@@ -0,0 +1,506 @@
/*
* Copyright (c) 1998, 2013, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.RenderingHints;
import java.lang.annotation.Native;
/**
* This class contains rendering hints that can be used by the
* {@link java.awt.Graphics2D} class, and classes that implement
* {@link java.awt.image.BufferedImageOp} and
* {@link java.awt.image.Raster}.
*/
public class SunHints {
/**
* Defines the type of all keys used to control various
* aspects of the rendering and imaging pipelines. Instances
* of this class are immutable and unique which means that
* tests for matches can be made using the == operator instead
* of the more expensive equals() method.
*/
public static class Key extends RenderingHints.Key {
String description;
/**
* Construct a key using the indicated private key. Each
* subclass of Key maintains its own unique domain of integer
* keys. No two objects with the same integer key and of the
* same specific subclass can be constructed. An exception
* will be thrown if an attempt is made to construct another
* object of a given class with the same integer key as a
* pre-existing instance of that subclass of Key.
*/
public Key(int privatekey, String description) {
super(privatekey);
this.description = description;
}
/**
* Returns the numeric index associated with this Key. This
* is useful for use in switch statements and quick lookups
* of the setting of a particular key.
*/
public final int getIndex() {
return intKey();
}
/**
* Returns a string representation of the Key.
*/
public final String toString() {
return description;
}
/**
* Returns true if the specified object is a valid value
* for this Key.
*/
public boolean isCompatibleValue(Object val) {
if (val instanceof Value) {
return ((Value)val).isCompatibleKey(this);
}
return false;
}
}
/**
* Defines the type of all "enumerative" values used to control
* various aspects of the rendering and imaging pipelines. Instances
* of this class are immutable and unique which means that
* tests for matches can be made using the == operator instead
* of the more expensive equals() method.
*/
public static class Value {
private SunHints.Key myKey;
private int index;
private String description;
private static Value[][] ValueObjects =
new Value[NUM_KEYS][VALS_PER_KEY];
private synchronized static void register(SunHints.Key key,
Value value) {
int kindex = key.getIndex();
int vindex = value.getIndex();
if (ValueObjects[kindex][vindex] != null) {
throw new InternalError("duplicate index: "+vindex);
}
ValueObjects[kindex][vindex] = value;
}
public static Value get(int keyindex, int valueindex) {
return ValueObjects[keyindex][valueindex];
}
/**
* Construct a value using the indicated private index. Each
* subclass of Value maintains its own unique domain of integer
* indices. Enforcing the uniqueness of the integer indices
* is left to the subclass.
*/
public Value(SunHints.Key key, int index, String description) {
this.myKey = key;
this.index = index;
this.description = description;
register(key, this);
}
/**
* Returns the numeric index associated with this Key. This
* is useful for use in switch statements and quick lookups
* of the setting of a particular key.
*/
public final int getIndex() {
return index;
}
/**
* Returns a string representation of this Value.
*/
public final String toString() {
return description;
}
/**
* Returns true if the specified object is a valid Key
* for this Value.
*/
public final boolean isCompatibleKey(Key k) {
return myKey == k;
}
/**
* The hash code for all SunHints.Value objects will be the same
* as the system identity code of the object as defined by the
* System.identityHashCode() method.
*/
public final int hashCode() {
return System.identityHashCode(this);
}
/**
* The equals method for all SunHints.Value objects will return
* the same result as the equality operator '=='.
*/
public final boolean equals(Object o) {
return this == o;
}
}
private static final int NUM_KEYS = 10;
private static final int VALS_PER_KEY = 8;
/**
* Rendering hint key and values
*/
@Native public static final int INTKEY_RENDERING = 0;
@Native public static final int INTVAL_RENDER_DEFAULT = 0;
@Native public static final int INTVAL_RENDER_SPEED = 1;
@Native public static final int INTVAL_RENDER_QUALITY = 2;
/**
* Antialiasing hint key and values
*/
@Native public static final int INTKEY_ANTIALIASING = 1;
@Native public static final int INTVAL_ANTIALIAS_DEFAULT = 0;
@Native public static final int INTVAL_ANTIALIAS_OFF = 1;
@Native public static final int INTVAL_ANTIALIAS_ON = 2;
/**
* Text antialiasing hint key and values
*/
@Native public static final int INTKEY_TEXT_ANTIALIASING = 2;
@Native public static final int INTVAL_TEXT_ANTIALIAS_DEFAULT = 0;
@Native public static final int INTVAL_TEXT_ANTIALIAS_OFF = 1;
@Native public static final int INTVAL_TEXT_ANTIALIAS_ON = 2;
@Native public static final int INTVAL_TEXT_ANTIALIAS_GASP = 3;
@Native public static final int INTVAL_TEXT_ANTIALIAS_LCD_HRGB = 4;
@Native public static final int INTVAL_TEXT_ANTIALIAS_LCD_HBGR = 5;
@Native public static final int INTVAL_TEXT_ANTIALIAS_LCD_VRGB = 6;
@Native public static final int INTVAL_TEXT_ANTIALIAS_LCD_VBGR = 7;
/**
* Font fractional metrics hint key and values
*/
@Native public static final int INTKEY_FRACTIONALMETRICS = 3;
@Native public static final int INTVAL_FRACTIONALMETRICS_DEFAULT = 0;
@Native public static final int INTVAL_FRACTIONALMETRICS_OFF = 1;
@Native public static final int INTVAL_FRACTIONALMETRICS_ON = 2;
/**
* Dithering hint key and values
*/
@Native public static final int INTKEY_DITHERING = 4;
@Native public static final int INTVAL_DITHER_DEFAULT = 0;
@Native public static final int INTVAL_DITHER_DISABLE = 1;
@Native public static final int INTVAL_DITHER_ENABLE = 2;
/**
* Interpolation hint key and values
*/
@Native public static final int INTKEY_INTERPOLATION = 5;
@Native public static final int INTVAL_INTERPOLATION_NEAREST_NEIGHBOR = 0;
@Native public static final int INTVAL_INTERPOLATION_BILINEAR = 1;
@Native public static final int INTVAL_INTERPOLATION_BICUBIC = 2;
/**
* Alpha interpolation hint key and values
*/
@Native public static final int INTKEY_ALPHA_INTERPOLATION = 6;
@Native public static final int INTVAL_ALPHA_INTERPOLATION_DEFAULT = 0;
@Native public static final int INTVAL_ALPHA_INTERPOLATION_SPEED = 1;
@Native public static final int INTVAL_ALPHA_INTERPOLATION_QUALITY = 2;
/**
* Color rendering hint key and values
*/
@Native public static final int INTKEY_COLOR_RENDERING = 7;
@Native public static final int INTVAL_COLOR_RENDER_DEFAULT = 0;
@Native public static final int INTVAL_COLOR_RENDER_SPEED = 1;
@Native public static final int INTVAL_COLOR_RENDER_QUALITY = 2;
/**
* Stroke normalization control hint key and values
*/
@Native public static final int INTKEY_STROKE_CONTROL = 8;
@Native public static final int INTVAL_STROKE_DEFAULT = 0;
@Native public static final int INTVAL_STROKE_NORMALIZE = 1;
@Native public static final int INTVAL_STROKE_PURE = 2;
/**
* Image scaling hint key and values
*/
@Native public static final int INTKEY_RESOLUTION_VARIANT = 9;
@Native public static final int INTVAL_RESOLUTION_VARIANT_DEFAULT = 0;
@Native public static final int INTVAL_RESOLUTION_VARIANT_OFF = 1;
@Native public static final int INTVAL_RESOLUTION_VARIANT_ON = 2;
/**
* LCD text contrast control hint key.
* Value is "100" to make discontiguous with the others which
* are all enumerative and are of a different class.
*/
@Native public static final int INTKEY_AATEXT_LCD_CONTRAST = 100;
/**
* Rendering hint key and value objects
*/
public static final Key KEY_RENDERING =
new SunHints.Key(SunHints.INTKEY_RENDERING,
"Global rendering quality key");
public static final Object VALUE_RENDER_SPEED =
new SunHints.Value(KEY_RENDERING,
SunHints.INTVAL_RENDER_SPEED,
"Fastest rendering methods");
public static final Object VALUE_RENDER_QUALITY =
new SunHints.Value(KEY_RENDERING,
SunHints.INTVAL_RENDER_QUALITY,
"Highest quality rendering methods");
public static final Object VALUE_RENDER_DEFAULT =
new SunHints.Value(KEY_RENDERING,
SunHints.INTVAL_RENDER_DEFAULT,
"Default rendering methods");
/**
* Antialiasing hint key and value objects
*/
public static final Key KEY_ANTIALIASING =
new SunHints.Key(SunHints.INTKEY_ANTIALIASING,
"Global antialiasing enable key");
public static final Object VALUE_ANTIALIAS_ON =
new SunHints.Value(KEY_ANTIALIASING,
SunHints.INTVAL_ANTIALIAS_ON,
"Antialiased rendering mode");
public static final Object VALUE_ANTIALIAS_OFF =
new SunHints.Value(KEY_ANTIALIASING,
SunHints.INTVAL_ANTIALIAS_OFF,
"Nonantialiased rendering mode");
public static final Object VALUE_ANTIALIAS_DEFAULT =
new SunHints.Value(KEY_ANTIALIASING,
SunHints.INTVAL_ANTIALIAS_DEFAULT,
"Default antialiasing rendering mode");
/**
* Text antialiasing hint key and value objects
*/
public static final Key KEY_TEXT_ANTIALIASING =
new SunHints.Key(SunHints.INTKEY_TEXT_ANTIALIASING,
"Text-specific antialiasing enable key");
public static final Object VALUE_TEXT_ANTIALIAS_ON =
new SunHints.Value(KEY_TEXT_ANTIALIASING,
SunHints.INTVAL_TEXT_ANTIALIAS_ON,
"Antialiased text mode");
public static final Object VALUE_TEXT_ANTIALIAS_OFF =
new SunHints.Value(KEY_TEXT_ANTIALIASING,
SunHints.INTVAL_TEXT_ANTIALIAS_OFF,
"Nonantialiased text mode");
public static final Object VALUE_TEXT_ANTIALIAS_DEFAULT =
new SunHints.Value(KEY_TEXT_ANTIALIASING,
SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT,
"Default antialiasing text mode");
public static final Object VALUE_TEXT_ANTIALIAS_GASP =
new SunHints.Value(KEY_TEXT_ANTIALIASING,
SunHints.INTVAL_TEXT_ANTIALIAS_GASP,
"gasp antialiasing text mode");
public static final Object VALUE_TEXT_ANTIALIAS_LCD_HRGB =
new SunHints.Value(KEY_TEXT_ANTIALIASING,
SunHints.INTVAL_TEXT_ANTIALIAS_LCD_HRGB,
"LCD HRGB antialiasing text mode");
public static final Object VALUE_TEXT_ANTIALIAS_LCD_HBGR =
new SunHints.Value(KEY_TEXT_ANTIALIASING,
SunHints.INTVAL_TEXT_ANTIALIAS_LCD_HBGR,
"LCD HBGR antialiasing text mode");
public static final Object VALUE_TEXT_ANTIALIAS_LCD_VRGB =
new SunHints.Value(KEY_TEXT_ANTIALIASING,
SunHints.INTVAL_TEXT_ANTIALIAS_LCD_VRGB,
"LCD VRGB antialiasing text mode");
public static final Object VALUE_TEXT_ANTIALIAS_LCD_VBGR =
new SunHints.Value(KEY_TEXT_ANTIALIASING,
SunHints.INTVAL_TEXT_ANTIALIAS_LCD_VBGR,
"LCD VBGR antialiasing text mode");
/**
* Font fractional metrics hint key and value objects
*/
public static final Key KEY_FRACTIONALMETRICS =
new SunHints.Key(SunHints.INTKEY_FRACTIONALMETRICS,
"Fractional metrics enable key");
public static final Object VALUE_FRACTIONALMETRICS_ON =
new SunHints.Value(KEY_FRACTIONALMETRICS,
SunHints.INTVAL_FRACTIONALMETRICS_ON,
"Fractional text metrics mode");
public static final Object VALUE_FRACTIONALMETRICS_OFF =
new SunHints.Value(KEY_FRACTIONALMETRICS,
SunHints.INTVAL_FRACTIONALMETRICS_OFF,
"Integer text metrics mode");
public static final Object VALUE_FRACTIONALMETRICS_DEFAULT =
new SunHints.Value(KEY_FRACTIONALMETRICS,
SunHints.INTVAL_FRACTIONALMETRICS_DEFAULT,
"Default fractional text metrics mode");
/**
* Dithering hint key and value objects
*/
public static final Key KEY_DITHERING =
new SunHints.Key(SunHints.INTKEY_DITHERING,
"Dithering quality key");
public static final Object VALUE_DITHER_ENABLE =
new SunHints.Value(KEY_DITHERING,
SunHints.INTVAL_DITHER_ENABLE,
"Dithered rendering mode");
public static final Object VALUE_DITHER_DISABLE =
new SunHints.Value(KEY_DITHERING,
SunHints.INTVAL_DITHER_DISABLE,
"Nondithered rendering mode");
public static final Object VALUE_DITHER_DEFAULT =
new SunHints.Value(KEY_DITHERING,
SunHints.INTVAL_DITHER_DEFAULT,
"Default dithering mode");
/**
* Interpolation hint key and value objects
*/
public static final Key KEY_INTERPOLATION =
new SunHints.Key(SunHints.INTKEY_INTERPOLATION,
"Image interpolation method key");
public static final Object VALUE_INTERPOLATION_NEAREST_NEIGHBOR =
new SunHints.Value(KEY_INTERPOLATION,
SunHints.INTVAL_INTERPOLATION_NEAREST_NEIGHBOR,
"Nearest Neighbor image interpolation mode");
public static final Object VALUE_INTERPOLATION_BILINEAR =
new SunHints.Value(KEY_INTERPOLATION,
SunHints.INTVAL_INTERPOLATION_BILINEAR,
"Bilinear image interpolation mode");
public static final Object VALUE_INTERPOLATION_BICUBIC =
new SunHints.Value(KEY_INTERPOLATION,
SunHints.INTVAL_INTERPOLATION_BICUBIC,
"Bicubic image interpolation mode");
/**
* Alpha interpolation hint key and value objects
*/
public static final Key KEY_ALPHA_INTERPOLATION =
new SunHints.Key(SunHints.INTKEY_ALPHA_INTERPOLATION,
"Alpha blending interpolation method key");
public static final Object VALUE_ALPHA_INTERPOLATION_SPEED =
new SunHints.Value(KEY_ALPHA_INTERPOLATION,
SunHints.INTVAL_ALPHA_INTERPOLATION_SPEED,
"Fastest alpha blending methods");
public static final Object VALUE_ALPHA_INTERPOLATION_QUALITY =
new SunHints.Value(KEY_ALPHA_INTERPOLATION,
SunHints.INTVAL_ALPHA_INTERPOLATION_QUALITY,
"Highest quality alpha blending methods");
public static final Object VALUE_ALPHA_INTERPOLATION_DEFAULT =
new SunHints.Value(KEY_ALPHA_INTERPOLATION,
SunHints.INTVAL_ALPHA_INTERPOLATION_DEFAULT,
"Default alpha blending methods");
/**
* Color rendering hint key and value objects
*/
public static final Key KEY_COLOR_RENDERING =
new SunHints.Key(SunHints.INTKEY_COLOR_RENDERING,
"Color rendering quality key");
public static final Object VALUE_COLOR_RENDER_SPEED =
new SunHints.Value(KEY_COLOR_RENDERING,
SunHints.INTVAL_COLOR_RENDER_SPEED,
"Fastest color rendering mode");
public static final Object VALUE_COLOR_RENDER_QUALITY =
new SunHints.Value(KEY_COLOR_RENDERING,
SunHints.INTVAL_COLOR_RENDER_QUALITY,
"Highest quality color rendering mode");
public static final Object VALUE_COLOR_RENDER_DEFAULT =
new SunHints.Value(KEY_COLOR_RENDERING,
SunHints.INTVAL_COLOR_RENDER_DEFAULT,
"Default color rendering mode");
/**
* Stroke normalization control hint key and value objects
*/
public static final Key KEY_STROKE_CONTROL =
new SunHints.Key(SunHints.INTKEY_STROKE_CONTROL,
"Stroke normalization control key");
public static final Object VALUE_STROKE_DEFAULT =
new SunHints.Value(KEY_STROKE_CONTROL,
SunHints.INTVAL_STROKE_DEFAULT,
"Default stroke normalization");
public static final Object VALUE_STROKE_NORMALIZE =
new SunHints.Value(KEY_STROKE_CONTROL,
SunHints.INTVAL_STROKE_NORMALIZE,
"Normalize strokes for consistent rendering");
public static final Object VALUE_STROKE_PURE =
new SunHints.Value(KEY_STROKE_CONTROL,
SunHints.INTVAL_STROKE_PURE,
"Pure stroke conversion for accurate paths");
/**
* Image resolution variant hint key and value objects
*/
public static final Key KEY_RESOLUTION_VARIANT =
new SunHints.Key(SunHints.INTKEY_RESOLUTION_VARIANT,
"Global image resolution variant key");
public static final Object VALUE_RESOLUTION_VARIANT_DEFAULT =
new SunHints.Value(KEY_RESOLUTION_VARIANT,
SunHints.INTVAL_RESOLUTION_VARIANT_DEFAULT,
"Choose image resolutions based on a default heuristic");
public static final Object VALUE_RESOLUTION_VARIANT_OFF =
new SunHints.Value(KEY_RESOLUTION_VARIANT,
SunHints.INTVAL_RESOLUTION_VARIANT_OFF,
"Use only the standard resolution of an image");
public static final Object VALUE_RESOLUTION_VARIANT_ON =
new SunHints.Value(KEY_RESOLUTION_VARIANT,
SunHints.INTVAL_RESOLUTION_VARIANT_ON,
"Always use resolution-specific variants of images");
public static class LCDContrastKey extends Key {
public LCDContrastKey(int privatekey, String description) {
super(privatekey, description);
}
/**
* Returns true if the specified object is a valid value
* for this Key. The allowable range is 100 to 250.
*/
public final boolean isCompatibleValue(Object val) {
if (val instanceof Integer) {
int ival = ((Integer)val).intValue();
return ival >= 100 && ival <= 250;
}
return false;
}
}
/**
* LCD text contrast hint key
*/
public static final RenderingHints.Key
KEY_TEXT_ANTIALIAS_LCD_CONTRAST =
new LCDContrastKey(SunHints.INTKEY_AATEXT_LCD_CONTRAST,
"Text-specific LCD contrast key");
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,191 @@
/*
* Copyright (c) 1997, 2005, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.*;
public class Symbol extends Charset {
public Symbol () {
super("Symbol", null);
}
public CharsetEncoder newEncoder() {
return new Encoder(this);
}
/* Seems like supporting a decoder is required, but we aren't going
* to be publically exposing this class, so no need to waste work
*/
public CharsetDecoder newDecoder() {
throw new Error("Decoder is not implemented for Symbol Charset");
}
public boolean contains(Charset cs) {
return cs instanceof Symbol;
}
private static class Encoder extends CharsetEncoder {
public Encoder(Charset cs) {
super(cs, 1.0f, 1.0f);
}
public boolean canEncode(char c) {
if (c >= 0x2200 && c <= 0x22ef) {
if (table_math[c - 0x2200] != 0x00) {
return true;
}
} else if (c >= 0x0391 && c <= 0x03d6) {
if (table_greek[c - 0x0391] != 0x00) {
return true;
}
}
return false;
}
protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) {
char[] sa = src.array();
int sp = src.arrayOffset() + src.position();
int sl = src.arrayOffset() + src.limit();
assert (sp <= sl);
sp = (sp <= sl ? sp : sl);
byte[] da = dst.array();
int dp = dst.arrayOffset() + dst.position();
int dl = dst.arrayOffset() + dst.limit();
assert (dp <= dl);
dp = (dp <= dl ? dp : dl);
try {
while (sp < sl) {
char c = sa[sp];
if (dl - dp < 1)
return CoderResult.OVERFLOW;
if (!canEncode(c))
return CoderResult.unmappableForLength(1);
sp++;
if (c >= 0x2200 && c <= 0x22ef){
da[dp++] = table_math[c - 0x2200];
} else if (c >= 0x0391 && c <= 0x03d6) {
da[dp++]= table_greek[c - 0x0391];
}
}
return CoderResult.UNDERFLOW;
} finally {
src.position(sp - src.arrayOffset());
dst.position(dp - dst.arrayOffset());
}
}
private static byte[] table_math = {
(byte)0042, (byte)0000, (byte)0144, (byte)0044,
(byte)0000, (byte)0306, (byte)0104, (byte)0321, // 00
(byte)0316, (byte)0317, (byte)0000, (byte)0000,
(byte)0000, (byte)0047, (byte)0000, (byte)0120,
(byte)0000, (byte)0345, (byte)0055, (byte)0000,
(byte)0000, (byte)0244, (byte)0000, (byte)0052, // 10
(byte)0260, (byte)0267, (byte)0326, (byte)0000,
(byte)0000, (byte)0265, (byte)0245, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0275,
(byte)0000, (byte)0000, (byte)0000, (byte)0331, // 20
(byte)0332, (byte)0307, (byte)0310, (byte)0362,
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0134, (byte)0000, (byte)0000, (byte)0000, // 30
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0176, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0100, (byte)0000, (byte)0000, // 40
(byte)0273, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000, // 50
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0271, (byte)0272, (byte)0000, (byte)0000,
(byte)0243, (byte)0263, (byte)0000, (byte)0000, // 60
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000, // 70
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0314, (byte)0311,
(byte)0313, (byte)0000, (byte)0315, (byte)0312, // 80
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0305, (byte)0000, (byte)0304, // 90
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0136, (byte)0000, (byte)0000, // a0
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000, // b0
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0340, (byte)0327, (byte)0000, (byte)0000, // c0
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000, // d0
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000, // e0
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0274,
};
private static byte[] table_greek = {
(byte)0101, (byte)0102, (byte)0107,
(byte)0104, (byte)0105, (byte)0132, (byte)0110, // 90
(byte)0121, (byte)0111, (byte)0113, (byte)0114,
(byte)0115, (byte)0116, (byte)0130, (byte)0117,
(byte)0120, (byte)0122, (byte)0000, (byte)0123,
(byte)0124, (byte)0125, (byte)0106, (byte)0103, // a0
(byte)0131, (byte)0127, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0141, (byte)0142, (byte)0147,
(byte)0144, (byte)0145, (byte)0172, (byte)0150, // b0
(byte)0161, (byte)0151, (byte)0153, (byte)0154,
(byte)0155, (byte)0156, (byte)0170, (byte)0157,
(byte)0160, (byte)0162, (byte)0126, (byte)0163,
(byte)0164, (byte)0165, (byte)0146, (byte)0143, // c0
(byte)0171, (byte)0167, (byte)0000, (byte)0000,
(byte)0000, (byte)0000, (byte)0000, (byte)0000,
(byte)0000, (byte)0112, (byte)0241, (byte)0000,
(byte)0000, (byte)0152, (byte)0166, // d0
};
/* The default implementation creates a decoder and we don't have one */
public boolean isLegalReplacement(byte[] repl) {
return true;
}
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2012, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.event.WindowEvent;
import java.awt.Window;
public class TimedWindowEvent extends WindowEvent {
private long time;
public long getWhen() {
return time;
}
public TimedWindowEvent(Window source, int id, Window opposite, long time) {
super(source, id, opposite);
this.time = time;
}
public TimedWindowEvent(Window source, int id, Window opposite,
int oldState, int newState, long time)
{
super(source, id, opposite, oldState, newState);
this.time = time;
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (c) 1997, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* An EventQueue subclass which adds selective tracing of events as they
* are posted to an EventQueue. Tracing is globally enabled and disabled
* by the AWT.TraceEventPosting property in awt.properties. <P>
*
* The optional AWT.NoTraceIDs property defines a list of AWTEvent IDs
* which should not be traced, such as MouseEvent.MOUSE_MOVED or PaintEvents.
* This list is declared by specifying the decimal value of each event's ID,
* separated by commas.
*
* @author Thomas Ball
*/
package sun.awt;
import java.awt.EventQueue;
import java.awt.AWTEvent;
import java.awt.Toolkit;
import java.util.StringTokenizer;
public class TracedEventQueue extends EventQueue {
// Determines whether any event tracing is enabled.
static boolean trace = false;
// The list of event IDs to ignore when tracing.
static int suppressedIDs[] = null;
static {
String s = Toolkit.getProperty("AWT.IgnoreEventIDs", "");
if (s.length() > 0) {
StringTokenizer st = new StringTokenizer(s, ",");
int nIDs = st.countTokens();
suppressedIDs = new int[nIDs];
for (int i = 0; i < nIDs; i++) {
String idString = st.nextToken();
try {
suppressedIDs[i] = Integer.parseInt(idString);
} catch (NumberFormatException e) {
System.err.println("Bad ID listed in AWT.IgnoreEventIDs " +
"in awt.properties: \"" +
idString + "\" -- skipped");
suppressedIDs[i] = 0;
}
}
} else {
suppressedIDs = new int[0];
}
}
public void postEvent(AWTEvent theEvent) {
boolean printEvent = true;
int id = theEvent.getID();
for (int i = 0; i < suppressedIDs.length; i++) {
if (id == suppressedIDs[i]) {
printEvent = false;
break;
}
}
if (printEvent) {
System.out.println(Thread.currentThread().getName() +
": " + theEvent);
}
super.postEvent(theEvent);
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 2005, 2011, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.AWTEvent;
import java.awt.Component;
/**
* Sent when one of the following events occur on the grabbed window: <ul>
* <li> it looses focus, but not to one of the owned windows
* <li> mouse click on the outside area happens (except for one of the owned windows)
* <li> switch to another application or desktop happens
* <li> click in the non-client area of the owning window or this window happens
* </ul>
*
* <p>Notice that this event is not generated on mouse click inside of the window area.
* <p>To listen for this event, install AWTEventListener with {@value sun.awt.SunToolkit#GRAB_EVENT_MASK}
*/
@SuppressWarnings("serial")
public class UngrabEvent extends AWTEvent {
private final static int UNGRAB_EVENT_ID = 1998;
public UngrabEvent(Component source) {
super(source, UNGRAB_EVENT_ID);
}
public String toString() {
return "sun.awt.UngrabEvent[" + getSource() + "]";
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (c) 1998, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.image.ComponentColorModel;
import java.awt.image.PixelInterleavedSampleModel;
import java.awt.image.WritableRaster;
import java.awt.image.Raster;
import java.awt.image.DataBuffer;
import java.awt.image.SampleModel;
import java.awt.color.ColorSpace;
import java.awt.Transparency;
/**
* This class creates a standard ComponentColorModel with the slight
* difference that it creates its Raster objects with the components
* in the reverse order from the base ComponentColorModel to match
* the ordering on a Windows 24-bit display.
*/
public class Win32ColorModel24 extends ComponentColorModel {
public Win32ColorModel24() {
super(ColorSpace.getInstance(ColorSpace.CS_sRGB),
new int[] {8, 8, 8}, false, false,
Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
}
/**
* Creates a WritableRaster with the specified width and height, that
* has a data layout (SampleModel) compatible with this ColorModel.
* @see WritableRaster
* @see SampleModel
*/
public WritableRaster createCompatibleWritableRaster (int w, int h) {
int[] bOffs = {2, 1, 0};
return Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
w, h, w*3, 3,
bOffs, null);
}
/**
* Creates a SampleModel with the specified width and height, that
* has a data layout compatible with this ColorModel.
* @see SampleModel
*/
public SampleModel createCompatibleSampleModel(int w, int h) {
int[] bOffs = {2, 1, 0};
return new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE,
w, h, 3, w*3, bOffs);
}
}

View File

@@ -0,0 +1,363 @@
/*
* Copyright (c) 2008, 2014, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.FontFormatException;
import java.awt.GraphicsEnvironment;
import java.io.File;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import sun.awt.windows.WFontConfiguration;
import sun.font.FontManager;
import sun.font.SunFontManager;
import sun.font.TrueTypeFont;
import sun.java2d.HeadlessGraphicsEnvironment;
import sun.java2d.SunGraphicsEnvironment;
/**
* The X11 implementation of {@link FontManager}.
*/
public final class Win32FontManager extends SunFontManager {
private static TrueTypeFont eudcFont;
static {
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
String eudcFile = getEUDCFontFile();
if (eudcFile != null) {
try {
/* Must use Java rasteriser since GDI doesn't
* enumerate (allow direct use) of EUDC fonts.
*/
eudcFont = new TrueTypeFont(eudcFile, null, 0,
true, false);
} catch (FontFormatException e) {
}
}
return null;
}
});
}
/* Used on Windows to obtain from the windows registry the name
* of a file containing the system EUFC font. If running in one of
* the locales for which this applies, and one is defined, the font
* defined by this file is appended to all composite fonts as a
* fallback component.
*/
private static native String getEUDCFontFile();
public TrueTypeFont getEUDCFont() {
return eudcFont;
}
public Win32FontManager() {
super();
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
/* Register the JRE fonts so that the native platform can
* access them. This is used only on Windows so that when
* printing the printer driver can access the fonts.
*/
registerJREFontsWithPlatform(jreFontDirName);
return null;
}
});
}
/**
* Whether registerFontFile expects absolute or relative
* font file names.
*/
protected boolean useAbsoluteFontFileNames() {
return false;
}
/* Unlike the shared code version, this expects a base file name -
* not a full path name.
* The font configuration file has base file names and the FontConfiguration
* class reports these back to the GraphicsEnvironment, so these
* are the componentFileNames of CompositeFonts.
*/
protected void registerFontFile(String fontFileName, String[] nativeNames,
int fontRank, boolean defer) {
// REMIND: case compare depends on platform
if (registeredFontFiles.contains(fontFileName)) {
return;
}
registeredFontFiles.add(fontFileName);
int fontFormat;
if (getTrueTypeFilter().accept(null, fontFileName)) {
fontFormat = SunFontManager.FONTFORMAT_TRUETYPE;
} else if (getType1Filter().accept(null, fontFileName)) {
fontFormat = SunFontManager.FONTFORMAT_TYPE1;
} else {
/* on windows we don't use/register native fonts */
return;
}
if (fontPath == null) {
fontPath = getPlatformFontPath(noType1Font);
}
/* Look in the JRE font directory first.
* This is playing it safe as we would want to find fonts in the
* JRE font directory ahead of those in the system directory
*/
String tmpFontPath = jreFontDirName+File.pathSeparator+fontPath;
StringTokenizer parser = new StringTokenizer(tmpFontPath,
File.pathSeparator);
boolean found = false;
try {
while (!found && parser.hasMoreTokens()) {
String newPath = parser.nextToken();
boolean isJREFont = newPath.equals(jreFontDirName);
File theFile = new File(newPath, fontFileName);
if (theFile.canRead()) {
found = true;
String path = theFile.getAbsolutePath();
if (defer) {
registerDeferredFont(fontFileName, path,
nativeNames,
fontFormat, isJREFont,
fontRank);
} else {
registerFontFile(path, nativeNames,
fontFormat, isJREFont,
fontRank);
}
break;
}
}
} catch (NoSuchElementException e) {
System.err.println(e);
}
if (!found) {
addToMissingFontFileList(fontFileName);
}
}
@Override
protected FontConfiguration createFontConfiguration() {
FontConfiguration fc = new WFontConfiguration(this);
fc.init();
return fc;
}
@Override
public FontConfiguration createFontConfiguration(boolean preferLocaleFonts,
boolean preferPropFonts) {
return new WFontConfiguration(this,
preferLocaleFonts,preferPropFonts);
}
protected void
populateFontFileNameMap(HashMap<String,String> fontToFileMap,
HashMap<String,String> fontToFamilyNameMap,
HashMap<String,ArrayList<String>>
familyToFontListMap,
Locale locale) {
populateFontFileNameMap0(fontToFileMap, fontToFamilyNameMap,
familyToFontListMap, locale);
}
private static native void
populateFontFileNameMap0(HashMap<String,String> fontToFileMap,
HashMap<String,String> fontToFamilyNameMap,
HashMap<String,ArrayList<String>>
familyToFontListMap,
Locale locale);
protected synchronized native String getFontPath(boolean noType1Fonts);
@Override
protected String[] getDefaultPlatformFont() {
String[] info = new String[2];
info[0] = "Arial";
info[1] = "c:\\windows\\fonts";
final String[] dirs = getPlatformFontDirs(true);
if (dirs.length > 1) {
String dir = (String)
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
for (int i=0; i<dirs.length; i++) {
String path =
dirs[i] + File.separator + "arial.ttf";
File file = new File(path);
if (file.exists()) {
return dirs[i];
}
}
return null;
}
});
if (dir != null) {
info[1] = dir;
}
} else {
info[1] = dirs[0];
}
info[1] = info[1] + File.separator + "arial.ttf";
return info;
}
/* register only TrueType/OpenType fonts
* Because these need to be registed just for use when printing,
* we defer the actual registration and the static initialiser
* for the printing class makes the call to registerJREFontsForPrinting()
*/
static String fontsForPrinting = null;
protected void registerJREFontsWithPlatform(String pathName) {
fontsForPrinting = pathName;
}
public static void registerJREFontsForPrinting() {
final String pathName;
synchronized (Win32GraphicsEnvironment.class) {
GraphicsEnvironment.getLocalGraphicsEnvironment();
if (fontsForPrinting == null) {
return;
}
pathName = fontsForPrinting;
fontsForPrinting = null;
}
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
File f1 = new File(pathName);
String[] ls = f1.list(SunFontManager.getInstance().
getTrueTypeFilter());
if (ls == null) {
return null;
}
for (int i=0; i <ls.length; i++ ) {
File fontFile = new File(f1, ls[i]);
registerFontWithPlatform(fontFile.getAbsolutePath());
}
return null;
}
});
}
protected static native void registerFontWithPlatform(String fontName);
protected static native void deRegisterFontWithPlatform(String fontName);
/**
* populate the map with the most common windows fonts.
*/
@Override
public HashMap<String, FamilyDescription> populateHardcodedFileNameMap() {
HashMap<String, FamilyDescription> platformFontMap
= new HashMap<String, FamilyDescription>();
FamilyDescription fd;
/* Segoe UI is the default UI font for Vista and later, and
* is used by the Win L&F which is used by FX too.
* Tahoma is used for the Win L&F on XP.
* Verdana is used in some FX UI controls.
*/
fd = new FamilyDescription();
fd.familyName = "Segoe UI";
fd.plainFullName = "Segoe UI";
fd.plainFileName = "segoeui.ttf";
fd.boldFullName = "Segoe UI Bold";
fd.boldFileName = "segoeuib.ttf";
fd.italicFullName = "Segoe UI Italic";
fd.italicFileName = "segoeuii.ttf";
fd.boldItalicFullName = "Segoe UI Bold Italic";
fd.boldItalicFileName = "segoeuiz.ttf";
platformFontMap.put("segoe", fd);
fd = new FamilyDescription();
fd.familyName = "Tahoma";
fd.plainFullName = "Tahoma";
fd.plainFileName = "tahoma.ttf";
fd.boldFullName = "Tahoma Bold";
fd.boldFileName = "tahomabd.ttf";
platformFontMap.put("tahoma", fd);
fd = new FamilyDescription();
fd.familyName = "Verdana";
fd.plainFullName = "Verdana";
fd.plainFileName = "verdana.TTF";
fd.boldFullName = "Verdana Bold";
fd.boldFileName = "verdanab.TTF";
fd.italicFullName = "Verdana Italic";
fd.italicFileName = "verdanai.TTF";
fd.boldItalicFullName = "Verdana Bold Italic";
fd.boldItalicFileName = "verdanaz.TTF";
platformFontMap.put("verdana", fd);
/* The following are important because they are the core
* members of the default "Dialog" font.
*/
fd = new FamilyDescription();
fd.familyName = "Arial";
fd.plainFullName = "Arial";
fd.plainFileName = "ARIAL.TTF";
fd.boldFullName = "Arial Bold";
fd.boldFileName = "ARIALBD.TTF";
fd.italicFullName = "Arial Italic";
fd.italicFileName = "ARIALI.TTF";
fd.boldItalicFullName = "Arial Bold Italic";
fd.boldItalicFileName = "ARIALBI.TTF";
platformFontMap.put("arial", fd);
fd = new FamilyDescription();
fd.familyName = "Symbol";
fd.plainFullName = "Symbol";
fd.plainFileName = "Symbol.TTF";
platformFontMap.put("symbol", fd);
fd = new FamilyDescription();
fd.familyName = "WingDings";
fd.plainFullName = "WingDings";
fd.plainFileName = "WINGDING.TTF";
platformFontMap.put("wingdings", fd);
return platformFontMap;
}
}

View File

@@ -0,0 +1,340 @@
/*
* Copyright (c) 1997, 2009, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.AWTException;
import java.awt.BufferCapabilities;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.ImageCapabilities;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Transparency;
import java.awt.Window;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DirectColorModel;
import java.awt.image.Raster;
import java.awt.image.VolatileImage;
import java.awt.image.WritableRaster;
import sun.awt.windows.WComponentPeer;
import sun.awt.image.OffScreenImage;
import sun.awt.image.SunVolatileImage;
import sun.awt.image.SurfaceManager;
import sun.java2d.SurfaceData;
import sun.java2d.InvalidPipeException;
import sun.java2d.loops.RenderLoops;
import sun.java2d.loops.SurfaceType;
import sun.java2d.loops.CompositeType;
import sun.java2d.windows.GDIWindowSurfaceData;
/**
* This is an implementation of a GraphicsConfiguration object for a
* single Win32 visual.
*
* @see GraphicsEnvironment
* @see GraphicsDevice
*/
public class Win32GraphicsConfig extends GraphicsConfiguration
implements DisplayChangedListener, SurfaceManager.ProxiedGraphicsConfig
{
protected Win32GraphicsDevice screen;
protected int visual; //PixelFormatID
protected RenderLoops solidloops;
private static native void initIDs();
static {
initIDs();
}
/**
* Returns a Win32GraphicsConfiguration object with the given device
* and PixelFormat. Note that this method does NOT check to ensure that
* the returned Win32GraphicsConfig will correctly support rendering into a
* Java window. This method is provided so that client code can do its
* own checking as to the appropriateness of a particular PixelFormat.
* Safer access to Win32GraphicsConfigurations is provided by
* Win32GraphicsDevice.getConfigurations().
*/
public static Win32GraphicsConfig getConfig(Win32GraphicsDevice device,
int pixFormatID)
{
return new Win32GraphicsConfig(device, pixFormatID);
}
/**
* @deprecated as of JDK version 1.3
* replaced by <code>getConfig()</code>
*/
@Deprecated
public Win32GraphicsConfig(GraphicsDevice device, int visualnum) {
this.screen = (Win32GraphicsDevice)device;
this.visual = visualnum;
((Win32GraphicsDevice)device).addDisplayChangedListener(this);
}
/**
* Return the graphics device associated with this configuration.
*/
public GraphicsDevice getDevice() {
return screen;
}
/**
* Return the PixelFormatIndex this GraphicsConfig uses
*/
public int getVisual() {
return visual;
}
public Object getProxyKey() {
return screen;
}
/**
* Return the RenderLoops this type of destination uses for
* solid fills and strokes.
*/
private SurfaceType sTypeOrig = null;
public synchronized RenderLoops getSolidLoops(SurfaceType stype) {
if (solidloops == null || sTypeOrig != stype) {
solidloops = SurfaceData.makeRenderLoops(SurfaceType.OpaqueColor,
CompositeType.SrcNoEa,
stype);
sTypeOrig = stype;
}
return solidloops;
}
/**
* Returns the color model associated with this configuration.
*/
public synchronized ColorModel getColorModel() {
return screen.getColorModel();
}
/**
* Returns a new color model for this configuration. This call
* is only used internally, by images and components that are
* associated with the graphics device. When attributes of that
* device change (for example, when the device palette is updated),
* then this device-based color model will be updated internally
* to reflect the new situation.
*/
public ColorModel getDeviceColorModel() {
return screen.getDynamicColorModel();
}
/**
* Returns the color model associated with this configuration that
* supports the specified transparency.
*/
public ColorModel getColorModel(int transparency) {
switch (transparency) {
case Transparency.OPAQUE:
return getColorModel();
case Transparency.BITMASK:
return new DirectColorModel(25, 0xff0000, 0xff00, 0xff, 0x1000000);
case Transparency.TRANSLUCENT:
return ColorModel.getRGBdefault();
default:
return null;
}
}
/**
* Returns the default Transform for this configuration. This
* Transform is typically the Identity transform for most normal
* screens. Device coordinates for screen and printer devices will
* have the origin in the upper left-hand corner of the target region of
* the device, with X coordinates
* increasing to the right and Y coordinates increasing downwards.
* For image buffers, this Transform will be the Identity transform.
*/
public AffineTransform getDefaultTransform() {
return new AffineTransform();
}
/**
*
* Returns a Transform that can be composed with the default Transform
* of a Graphics2D so that 72 units in user space will equal 1 inch
* in device space.
* Given a Graphics2D, g, one can reset the transformation to create
* such a mapping by using the following pseudocode:
* <pre>
* GraphicsConfiguration gc = g.getGraphicsConfiguration();
*
* g.setTransform(gc.getDefaultTransform());
* g.transform(gc.getNormalizingTransform());
* </pre>
* Note that sometimes this Transform will be identity (e.g. for
* printers or metafile output) and that this Transform is only
* as accurate as the information supplied by the underlying system.
* For image buffers, this Transform will be the Identity transform,
* since there is no valid distance measurement.
*/
public AffineTransform getNormalizingTransform() {
Win32GraphicsEnvironment ge = (Win32GraphicsEnvironment)
GraphicsEnvironment.getLocalGraphicsEnvironment();
double xscale = ge.getXResolution() / 72.0;
double yscale = ge.getYResolution() / 72.0;
return new AffineTransform(xscale, 0.0, 0.0, yscale, 0.0, 0.0);
}
public String toString() {
return (super.toString()+"[dev="+screen+",pixfmt="+visual+"]");
}
private native Rectangle getBounds(int screen);
public Rectangle getBounds() {
return getBounds(screen.getScreen());
}
public synchronized void displayChanged() {
solidloops = null;
}
public void paletteChanged() {}
/**
* The following methods are invoked from WComponentPeer.java rather
* than having the Win32-dependent implementations hardcoded in that
* class. This way the appropriate actions are taken based on the peer's
* GraphicsConfig, whether it is a Win32GraphicsConfig or a
* WGLGraphicsConfig.
*/
/**
* Creates a new SurfaceData that will be associated with the given
* WComponentPeer.
*/
public SurfaceData createSurfaceData(WComponentPeer peer,
int numBackBuffers)
{
return GDIWindowSurfaceData.createData(peer);
}
/**
* Creates a new managed image of the given width and height
* that is associated with the target Component.
*/
public Image createAcceleratedImage(Component target,
int width, int height)
{
ColorModel model = getColorModel(Transparency.OPAQUE);
WritableRaster wr =
model.createCompatibleWritableRaster(width, height);
return new OffScreenImage(target, model, wr,
model.isAlphaPremultiplied());
}
/**
* The following methods correspond to the multibuffering methods in
* WComponentPeer.java...
*/
/**
* Checks that the requested configuration is natively supported; if not,
* an AWTException is thrown.
*/
public void assertOperationSupported(Component target,
int numBuffers,
BufferCapabilities caps)
throws AWTException
{
// the default pipeline doesn't support flip buffer strategy
throw new AWTException(
"The operation requested is not supported");
}
/**
* This method is called from WComponentPeer when a surface data is replaced
* REMIND: while the default pipeline doesn't support flipping, it may
* happen that the accelerated device may have this graphics config
* (like if the device restoration failed when one device exits fs mode
* while others remain).
*/
public VolatileImage createBackBuffer(WComponentPeer peer) {
Component target = (Component)peer.getTarget();
return new SunVolatileImage(target,
target.getWidth(), target.getHeight(),
Boolean.TRUE);
}
/**
* Performs the native flip operation for the given target Component.
*
* REMIND: we should really not get here because that would mean that
* a FLIP BufferStrategy has been created, and one could only be created
* if accelerated pipeline is present but in some rare (and transitional)
* cases it may happen that the accelerated graphics device may have a
* default graphics configuraiton, so this is just a precaution.
*/
public void flip(WComponentPeer peer,
Component target, VolatileImage backBuffer,
int x1, int y1, int x2, int y2,
BufferCapabilities.FlipContents flipAction)
{
if (flipAction == BufferCapabilities.FlipContents.COPIED ||
flipAction == BufferCapabilities.FlipContents.UNDEFINED) {
Graphics g = peer.getGraphics();
try {
g.drawImage(backBuffer,
x1, y1, x2, y2,
x1, y1, x2, y2,
null);
} finally {
g.dispose();
}
} else if (flipAction == BufferCapabilities.FlipContents.BACKGROUND) {
Graphics g = backBuffer.getGraphics();
try {
g.setColor(target.getBackground());
g.fillRect(0, 0,
backBuffer.getWidth(),
backBuffer.getHeight());
} finally {
g.dispose();
}
}
// the rest of the flip actions are not supported
}
@Override
public boolean isTranslucencyCapable() {
//XXX: worth checking if 8-bit? Anyway, it doesn't hurt.
return true;
}
}

View File

@@ -0,0 +1,637 @@
/*
* Copyright (c) 1997, 2010, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.AWTPermission;
import java.awt.GraphicsDevice;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.DisplayMode;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.image.ColorModel;
import java.util.ArrayList;
import java.util.Vector;
import java.awt.peer.WindowPeer;
import sun.awt.windows.WWindowPeer;
import sun.java2d.opengl.WGLGraphicsConfig;
import sun.java2d.windows.WindowsFlags;
/**
* This is an implementation of a GraphicsDevice object for a single
* Win32 screen.
*
* @see GraphicsEnvironment
* @see GraphicsConfiguration
*/
public class Win32GraphicsDevice extends GraphicsDevice implements
DisplayChangedListener {
int screen;
ColorModel dynamicColorModel; // updated with dev changes
ColorModel colorModel; // static for device
protected GraphicsConfiguration[] configs;
protected GraphicsConfiguration defaultConfig;
private final String idString;
protected String descString;
// Note that we do not synchronize access to this variable - it doesn't
// really matter if a thread does an operation on graphics device which is
// about to become invalid (or already become) - we are prepared to deal
// with this on the native level.
private boolean valid;
// keep track of top-level windows on this display
private SunDisplayChanger topLevels = new SunDisplayChanger();
// REMIND: we may disable the use of pixel formats for some accelerated
// pipelines which are mutually exclusive with opengl, for which
// pixel formats were added in the first place
protected static boolean pfDisabled;
private static AWTPermission fullScreenExclusivePermission;
// the original display mode we had before entering the fullscreen
// mode
private DisplayMode defaultDisplayMode;
// activation/deactivation listener for the full-screen window
private WindowListener fsWindowListener;
static {
// 4455041 - Even when ddraw is disabled, ddraw.dll is loaded when
// pixel format calls are made. This causes problems when a Java app
// is run as an NT service. To prevent the loading of ddraw.dll
// completely, sun.awt.nopixfmt should be set as well. Apps which use
// OpenGL w/ Java probably don't want to set this.
String nopixfmt = (String)java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("sun.awt.nopixfmt"));
pfDisabled = (nopixfmt != null);
initIDs();
}
private static native void initIDs();
native void initDevice(int screen);
public Win32GraphicsDevice(int screennum) {
this.screen = screennum;
// we cache the strings because we want toString() and getIDstring
// to reflect the original screen number (which may change if the
// device is removed)
idString = "\\Display"+screen;
// REMIND: may be should use class name?
descString = "Win32GraphicsDevice[screen=" + screen;
valid = true;
initDevice(screennum);
}
/**
* Returns the type of the graphics device.
* @see #TYPE_RASTER_SCREEN
* @see #TYPE_PRINTER
* @see #TYPE_IMAGE_BUFFER
*/
public int getType() {
return TYPE_RASTER_SCREEN;
}
/**
* Returns the Win32 screen of the device.
*/
public int getScreen() {
return screen;
}
/**
* Returns whether this is a valid devicie. Device can become
* invalid as a result of device removal event.
*/
public boolean isValid() {
return valid;
}
/**
* Called from native code when the device was removed.
*
* @param defaultScreen the current default screen
*/
protected void invalidate(int defaultScreen) {
valid = false;
screen = defaultScreen;
}
/**
* Returns the identification string associated with this graphics
* device.
*/
public String getIDstring() {
return idString;
}
/**
* Returns all of the graphics
* configurations associated with this graphics device.
*/
public GraphicsConfiguration[] getConfigurations() {
if (configs==null) {
if (WindowsFlags.isOGLEnabled() && isDefaultDevice()) {
defaultConfig = getDefaultConfiguration();
if (defaultConfig != null) {
configs = new GraphicsConfiguration[1];
configs[0] = defaultConfig;
return configs.clone();
}
}
int max = getMaxConfigs(screen);
int defaultPixID = getDefaultPixID(screen);
Vector v = new Vector( max );
if (defaultPixID == 0) {
// Workaround for failing GDI calls
defaultConfig = Win32GraphicsConfig.getConfig(this,
defaultPixID);
v.addElement(defaultConfig);
}
else {
for (int i = 1; i <= max; i++) {
if (isPixFmtSupported(i, screen)) {
if (i == defaultPixID) {
defaultConfig = Win32GraphicsConfig.getConfig(
this, i);
v.addElement(defaultConfig);
}
else {
v.addElement(Win32GraphicsConfig.getConfig(
this, i));
}
}
}
}
configs = new GraphicsConfiguration[v.size()];
v.copyInto(configs);
}
return configs.clone();
}
/**
* Returns the maximum number of graphics configurations available, or 1
* if PixelFormat calls fail or are disabled.
* This number is less than or equal to the number of graphics
* configurations supported.
*/
protected int getMaxConfigs(int screen) {
if (pfDisabled) {
return 1;
} else {
return getMaxConfigsImpl(screen);
}
}
private native int getMaxConfigsImpl(int screen);
/**
* Returns whether or not the PixelFormat indicated by index is
* supported. Supported PixelFormats support drawing to a Window
* (PFD_DRAW_TO_WINDOW), support GDI (PFD_SUPPORT_GDI), and in the
* case of an 8-bit format (cColorBits <= 8) uses indexed colors
* (iPixelType == PFD_TYPE_COLORINDEX).
* We use the index 0 to indicate that PixelFormat calls don't work, or
* are disabled. Do not call this function with an index of 0.
* @param index a PixelFormat index
*/
protected native boolean isPixFmtSupported(int index, int screen);
/**
* Returns the PixelFormatID of the default graphics configuration
* associated with this graphics device, or 0 if PixelFormats calls fail or
* are disabled.
*/
protected int getDefaultPixID(int screen) {
if (pfDisabled) {
return 0;
} else {
return getDefaultPixIDImpl(screen);
}
}
/**
* Returns the default PixelFormat ID from GDI. Do not call if PixelFormats
* are disabled.
*/
private native int getDefaultPixIDImpl(int screen);
/**
* Returns the default graphics configuration
* associated with this graphics device.
*/
public GraphicsConfiguration getDefaultConfiguration() {
if (defaultConfig == null) {
// first try to create a WGLGraphicsConfig if OGL is enabled
// REMIND: the WGL code does not yet work properly in multimon
// situations, so we will fallback on GDI if we are not on the
// default device...
if (WindowsFlags.isOGLEnabled() && isDefaultDevice()) {
int defPixID = WGLGraphicsConfig.getDefaultPixFmt(screen);
defaultConfig = WGLGraphicsConfig.getConfig(this, defPixID);
if (WindowsFlags.isOGLVerbose()) {
if (defaultConfig != null) {
System.out.print("OpenGL pipeline enabled");
} else {
System.out.print("Could not enable OpenGL pipeline");
}
System.out.println(" for default config on screen " +
screen);
}
}
// Fix for 4669614. Most apps are not concerned with PixelFormats,
// yet we ALWAYS used them for determining ColorModels and such.
// By passing in 0 as the PixelFormatID here, we signal that
// PixelFormats should not be used, thus avoid loading the opengl
// library. Apps concerned with PixelFormats can still use
// GraphicsConfiguration.getConfigurations().
// Note that calling native pixel format functions tends to cause
// problems between those functions (which are OpenGL-related)
// and our use of DirectX. For example, some Matrox boards will
// crash or hang calling these functions when any app is running
// in DirectX fullscreen mode. So avoiding these calls unless
// absolutely necessary is preferable.
if (defaultConfig == null) {
defaultConfig = Win32GraphicsConfig.getConfig(this, 0);
}
}
return defaultConfig;
}
public String toString() {
return valid ? descString + "]" : descString + ", removed]";
}
/**
* Returns true if this is the default GraphicsDevice for the
* GraphicsEnvironment.
*/
private boolean isDefaultDevice() {
return (this ==
GraphicsEnvironment.
getLocalGraphicsEnvironment().getDefaultScreenDevice());
}
private static boolean isFSExclusiveModeAllowed() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
if (fullScreenExclusivePermission == null) {
fullScreenExclusivePermission =
new AWTPermission("fullScreenExclusive");
}
try {
security.checkPermission(fullScreenExclusivePermission);
} catch (SecurityException e) {
return false;
}
}
return true;
}
/**
* returns true unless we're not allowed to use fullscreen mode.
*/
@Override
public boolean isFullScreenSupported() {
return isFSExclusiveModeAllowed();
}
@Override
public synchronized void setFullScreenWindow(Window w) {
Window old = getFullScreenWindow();
if (w == old) {
return;
}
if (!isFullScreenSupported()) {
super.setFullScreenWindow(w);
return;
}
// Enter windowed mode.
if (old != null) {
// restore the original display mode
if (defaultDisplayMode != null) {
setDisplayMode(defaultDisplayMode);
// we set the default display mode to null here
// because the default mode could change during
// the life of the application (user can change it through
// the desktop properties dialog, for example), so
// we need to record it every time prior to
// entering the fullscreen mode.
defaultDisplayMode = null;
}
WWindowPeer peer = (WWindowPeer)old.getPeer();
if (peer != null) {
peer.setFullScreenExclusiveModeState(false);
// we used to destroy the buffers on exiting fs mode, this
// is no longer needed since fs change will cause a surface
// data replacement
synchronized(peer) {
exitFullScreenExclusive(screen, peer);
}
}
removeFSWindowListener(old);
}
super.setFullScreenWindow(w);
if (w != null) {
// always record the default display mode prior to going
// fullscreen
defaultDisplayMode = getDisplayMode();
addFSWindowListener(w);
// Enter full screen exclusive mode.
WWindowPeer peer = (WWindowPeer)w.getPeer();
if (peer != null) {
synchronized(peer) {
enterFullScreenExclusive(screen, peer);
// Note: removed replaceSurfaceData() call because
// changing the window size or making it visible
// will cause this anyway, and both of these events happen
// as part of switching into fullscreen mode.
}
peer.setFullScreenExclusiveModeState(true);
}
// fix for 4868278
peer.updateGC();
}
}
// Entering and exiting full-screen mode are done within a
// tree-lock and should never lock on any resources which are
// required by other threads which may have them and may require
// the tree-lock.
// REMIND: in the future these methods may need to become protected so that
// subclasses could override them and use appropriate api other than GDI
// for implementing these functions.
protected native void enterFullScreenExclusive(int screen, WindowPeer w);
protected native void exitFullScreenExclusive(int screen, WindowPeer w);
@Override
public boolean isDisplayChangeSupported() {
return (isFullScreenSupported() && getFullScreenWindow() != null);
}
@Override
public synchronized void setDisplayMode(DisplayMode dm) {
if (!isDisplayChangeSupported()) {
super.setDisplayMode(dm);
return;
}
if (dm == null || (dm = getMatchingDisplayMode(dm)) == null) {
throw new IllegalArgumentException("Invalid display mode");
}
if (getDisplayMode().equals(dm)) {
return;
}
Window w = getFullScreenWindow();
if (w != null) {
WWindowPeer peer = (WWindowPeer)w.getPeer();
configDisplayMode(screen, peer, dm.getWidth(), dm.getHeight(),
dm.getBitDepth(), dm.getRefreshRate());
// resize the fullscreen window to the dimensions of the new
// display mode
Rectangle screenBounds = getDefaultConfiguration().getBounds();
w.setBounds(screenBounds.x, screenBounds.y,
dm.getWidth(), dm.getHeight());
// Note: no call to replaceSurfaceData is required here since
// replacement will be caused by an upcoming display change event
} else {
throw new IllegalStateException("Must be in fullscreen mode " +
"in order to set display mode");
}
}
protected native DisplayMode getCurrentDisplayMode(int screen);
protected native void configDisplayMode(int screen, WindowPeer w, int width,
int height, int bitDepth,
int refreshRate);
protected native void enumDisplayModes(int screen, ArrayList modes);
@Override
public synchronized DisplayMode getDisplayMode() {
DisplayMode res = getCurrentDisplayMode(screen);
return res;
}
@Override
public synchronized DisplayMode[] getDisplayModes() {
ArrayList modes = new ArrayList();
enumDisplayModes(screen, modes);
int listSize = modes.size();
DisplayMode[] retArray = new DisplayMode[listSize];
for (int i = 0; i < listSize; i++) {
retArray[i] = (DisplayMode)modes.get(i);
}
return retArray;
}
protected synchronized DisplayMode getMatchingDisplayMode(DisplayMode dm) {
if (!isDisplayChangeSupported()) {
return null;
}
DisplayMode[] modes = getDisplayModes();
for (DisplayMode mode : modes) {
if (dm.equals(mode) ||
(dm.getRefreshRate() == DisplayMode.REFRESH_RATE_UNKNOWN &&
dm.getWidth() == mode.getWidth() &&
dm.getHeight() == mode.getHeight() &&
dm.getBitDepth() == mode.getBitDepth()))
{
return mode;
}
}
return null;
}
/*
* From the DisplayChangeListener interface.
* Called from Win32GraphicsEnvironment when the display settings have
* changed.
*/
public void displayChanged() {
dynamicColorModel = null;
defaultConfig = null;
configs = null;
// pass on to all top-level windows on this display
topLevels.notifyListeners();
}
/**
* Part of the DisplayChangedListener interface: devices
* do not need to react to this event
*/
public void paletteChanged() {
}
/*
* Add a DisplayChangeListener to be notified when the display settings
* are changed. Typically, only top-level containers need to be added
* to Win32GraphicsDevice.
*/
public void addDisplayChangedListener(DisplayChangedListener client) {
topLevels.add(client);
}
/*
* Remove a DisplayChangeListener from this Win32GraphicsDevice
*/
public void removeDisplayChangedListener(DisplayChangedListener client) {
topLevels.remove(client);
}
/**
* Creates and returns the color model associated with this device
*/
private native ColorModel makeColorModel (int screen,
boolean dynamic);
/**
* Returns a dynamic ColorModel which is updated when there
* are any changes (e.g., palette changes) in the device
*/
public ColorModel getDynamicColorModel() {
if (dynamicColorModel == null) {
dynamicColorModel = makeColorModel(screen, true);
}
return dynamicColorModel;
}
/**
* Returns the non-dynamic ColorModel associated with this device
*/
public ColorModel getColorModel() {
if (colorModel == null) {
colorModel = makeColorModel(screen, false);
}
return colorModel;
}
/**
* WindowAdapter class responsible for de/iconifying full-screen window
* of this device.
*
* The listener restores the default display mode when window is iconified
* and sets it back to the one set by the user on de-iconification.
*/
private static class Win32FSWindowAdapter extends WindowAdapter {
private Win32GraphicsDevice device;
private DisplayMode dm;
Win32FSWindowAdapter(Win32GraphicsDevice device) {
this.device = device;
}
private void setFSWindowsState(Window other, int state) {
GraphicsDevice gds[] =
GraphicsEnvironment.getLocalGraphicsEnvironment().
getScreenDevices();
// check if the de/activation was caused by other
// fs window and ignore the event if that's the case
if (other != null) {
for (GraphicsDevice gd : gds) {
if (other == gd.getFullScreenWindow()) {
return;
}
}
}
// otherwise apply state to all fullscreen windows
for (GraphicsDevice gd : gds) {
Window fsw = gd.getFullScreenWindow();
if (fsw instanceof Frame) {
((Frame)fsw).setExtendedState(state);
}
}
}
@Override
public void windowDeactivated(WindowEvent e) {
setFSWindowsState(e.getOppositeWindow(), Frame.ICONIFIED);
}
@Override
public void windowActivated(WindowEvent e) {
setFSWindowsState(e.getOppositeWindow(), Frame.NORMAL);
}
@Override
public void windowIconified(WindowEvent e) {
// restore the default display mode for this device
DisplayMode ddm = device.defaultDisplayMode;
if (ddm != null) {
dm = device.getDisplayMode();
device.setDisplayMode(ddm);
}
}
@Override
public void windowDeiconified(WindowEvent e) {
// restore the user-set display mode for this device
if (dm != null) {
device.setDisplayMode(dm);
dm = null;
}
}
}
/**
* Adds a WindowListener to be used as
* activation/deactivation listener for the current full-screen window.
*
* @param w full-screen window
*/
protected void addFSWindowListener(final Window w) {
// Note: even though we create a listener for Window instances of
// fs windows they will not receive window events.
fsWindowListener = new Win32FSWindowAdapter(this);
// Fix for 6709453. Using invokeLater to avoid listening
// for the events already posted to the queue.
EventQueue.invokeLater(new Runnable() {
public void run() {
w.addWindowListener(fsWindowListener);
}
});
}
/**
* Removes the fs window listener.
*
* @param w full-screen window
*/
protected void removeFSWindowListener(Window w) {
w.removeWindowListener(fsWindowListener);
fsWindowListener = null;
}
}

View File

@@ -0,0 +1,267 @@
/*
* Copyright (c) 1997, 2013, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.AWTError;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.awt.peer.ComponentPeer;
import java.io.File;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import sun.awt.DisplayChangedListener;
import sun.awt.SunDisplayChanger;
import sun.awt.windows.WPrinterJob;
import sun.awt.windows.WToolkit;
import sun.java2d.SunGraphicsEnvironment;
import sun.java2d.SurfaceManagerFactory;
import sun.java2d.WindowsSurfaceManagerFactory;
import sun.java2d.d3d.D3DGraphicsDevice;
import sun.java2d.windows.WindowsFlags;
/**
* This is an implementation of a GraphicsEnvironment object for the
* default local GraphicsEnvironment used by the Java Runtime Environment
* for Windows.
*
* @see GraphicsDevice
* @see GraphicsConfiguration
*/
public class Win32GraphicsEnvironment
extends SunGraphicsEnvironment
{
static {
// Ensure awt is loaded already. Also, this forces static init
// of WToolkit and Toolkit, which we depend upon
WToolkit.loadLibraries();
// setup flags before initializing native layer
WindowsFlags.initFlags();
initDisplayWrapper();
// Install correct surface manager factory.
SurfaceManagerFactory.setInstance(new WindowsSurfaceManagerFactory());
}
/**
* Initializes native components of the graphics environment. This
* includes everything from the native GraphicsDevice elements to
* the DirectX rendering layer.
*/
private static native void initDisplay();
private static boolean displayInitialized; // = false;
public static void initDisplayWrapper() {
if (!displayInitialized) {
displayInitialized = true;
initDisplay();
}
}
public Win32GraphicsEnvironment() {
}
protected native int getNumScreens();
protected native int getDefaultScreen();
public GraphicsDevice getDefaultScreenDevice() {
GraphicsDevice[] screens = getScreenDevices();
if (screens.length == 0) {
throw new AWTError("no screen devices");
}
int index = getDefaultScreen();
return screens[0 < index && index < screens.length ? index : 0];
}
/**
* Returns the number of pixels per logical inch along the screen width.
* In a system with multiple display monitors, this value is the same for
* all monitors.
* @returns number of pixels per logical inch in X direction
*/
public native int getXResolution();
/**
* Returns the number of pixels per logical inch along the screen height.
* In a system with multiple display monitors, this value is the same for
* all monitors.
* @returns number of pixels per logical inch in Y direction
*/
public native int getYResolution();
/*
* ----DISPLAY CHANGE SUPPORT----
*/
// list of invalidated graphics devices (those which were removed)
private ArrayList<WeakReference<Win32GraphicsDevice>> oldDevices;
/*
* From DisplayChangeListener interface.
* Called from WToolkit and executed on the event thread when the
* display settings are changed.
*/
@Override
public void displayChanged() {
// getNumScreens() will return the correct current number of screens
GraphicsDevice newDevices[] = new GraphicsDevice[getNumScreens()];
GraphicsDevice oldScreens[] = screens;
// go through the list of current devices and determine if they
// could be reused, or will have to be replaced
if (oldScreens != null) {
for (int i = 0; i < oldScreens.length; i++) {
if (!(screens[i] instanceof Win32GraphicsDevice)) {
// REMIND: can we ever have anything other than Win32GD?
assert (false) : oldScreens[i];
continue;
}
Win32GraphicsDevice gd = (Win32GraphicsDevice)oldScreens[i];
// devices may be invalidated from the native code when the
// display change happens (device add/removal also causes a
// display change)
if (!gd.isValid()) {
if (oldDevices == null) {
oldDevices =
new ArrayList<WeakReference<Win32GraphicsDevice>>();
}
oldDevices.add(new WeakReference<Win32GraphicsDevice>(gd));
} else if (i < newDevices.length) {
// reuse the device
newDevices[i] = gd;
}
}
oldScreens = null;
}
// create the new devices (those that weren't reused)
for (int i = 0; i < newDevices.length; i++) {
if (newDevices[i] == null) {
newDevices[i] = makeScreenDevice(i);
}
}
// install the new array of devices
// Note: no synchronization here, it doesn't matter if a thread gets
// a new or an old array this time around
screens = newDevices;
for (GraphicsDevice gd : screens) {
if (gd instanceof DisplayChangedListener) {
((DisplayChangedListener)gd).displayChanged();
}
}
// re-invalidate all old devices. It's needed because those in the list
// may become "invalid" again - if the current default device is removed,
// for example. Also, they need to be notified about display
// changes as well.
if (oldDevices != null) {
int defScreen = getDefaultScreen();
for (ListIterator<WeakReference<Win32GraphicsDevice>> it =
oldDevices.listIterator(); it.hasNext();)
{
Win32GraphicsDevice gd = it.next().get();
if (gd != null) {
gd.invalidate(defScreen);
gd.displayChanged();
} else {
// no more references to this device, remove it
it.remove();
}
}
}
// Reset the static GC for the (possibly new) default screen
WToolkit.resetGC();
// notify SunDisplayChanger list (e.g. VolatileSurfaceManagers and
// CachingSurfaceManagers) about the display change event
displayChanger.notifyListeners();
// note: do not call super.displayChanged, we've already done everything
}
/*
* ----END DISPLAY CHANGE SUPPORT----
*/
protected GraphicsDevice makeScreenDevice(int screennum) {
GraphicsDevice device = null;
if (WindowsFlags.isD3DEnabled()) {
device = D3DGraphicsDevice.createDevice(screennum);
}
if (device == null) {
device = new Win32GraphicsDevice(screennum);
}
return device;
}
public boolean isDisplayLocal() {
return true;
}
@Override
public boolean isFlipStrategyPreferred(ComponentPeer peer) {
GraphicsConfiguration gc;
if (peer != null && (gc = peer.getGraphicsConfiguration()) != null) {
GraphicsDevice gd = gc.getDevice();
if (gd instanceof D3DGraphicsDevice) {
return ((D3DGraphicsDevice)gd).isD3DEnabledOnDevice();
}
}
return false;
}
private static volatile boolean isDWMCompositionEnabled;
/**
* Returns true if dwm composition is currently enabled, false otherwise.
*
* @return true if dwm composition is enabled, false otherwise
*/
public static boolean isDWMCompositionEnabled() {
return isDWMCompositionEnabled;
}
/**
* Called from the native code when DWM composition state changed.
* May be called multiple times during the lifetime of the application.
* REMIND: we may want to create a listener mechanism for this.
*
* Note: called on the Toolkit thread, no user code or locks are allowed.
*
* @param enabled indicates the state of dwm composition
*/
private static void dwmCompositionChanged(boolean enabled) {
isDWMCompositionEnabled = enabled;
}
/**
* Used to find out if the OS is Windows Vista or later.
*
* @return {@code true} if the OS is Vista or later, {@code false} otherwise
*/
public static native boolean isVistaOS();
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 1999, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
import java.awt.event.WindowEvent;
/**
* Interface for listening to WINDOW_CLOSING events before and
* after they are posted to the queue.
*/
public interface WindowClosingListener {
/**
* Called before a WINDOW_CLOSING event gets posted to the queue.
* @param event The WINDOW_CLOSING event that will be posted.
* @return A RuntimeException if the result of this function
* call needs to interrupt a blocking thread. The exception
* returned will be thrown from that thread. This function
* should return null otherwise.
*/
RuntimeException windowClosingNotify(WindowEvent event);
/**
* Called after a WINDOW_CLOSING event gets posted to the queue.
* @param event The WINDOW_CLOSING event that has been posted.
* @return A RuntimeException if the result of this function
* call needs to interrupt a blocking thread. The exception
* returned will be thrown from that thread. This function
* should return null otherwise.
*/
RuntimeException windowClosingDelivered(WindowEvent event);
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 1999, 2007, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
/**
* Interface for identifying and casting toolkits that support
* WindowClosingListeners.
*/
public interface WindowClosingSupport {
WindowClosingListener getWindowClosingListener();
void setWindowClosingListener(WindowClosingListener wcl);
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2004, 2005, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt;
/**
* Classes implementing this interface have public getWindow method,
* returning handle to the native window.
*/
public interface WindowIDProvider {
public long getWindow();
}

View File

@@ -0,0 +1,173 @@
/*
* Copyright (c) 2000, 2013, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.datatransfer;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* Reads all of the data from the system Clipboard which the data transfer
* subsystem knows how to translate. This includes all text data, File Lists,
* Serializable objects, Remote objects, and properly registered, arbitrary
* data as InputStreams. The data is stored in byte format until requested
* by client code. At that point, the data is converted, if necessary, into
* the proper format to deliver to the application.
*
* This hybrid pre-fetch/delayed-rendering approach allows us to circumvent
* the API restriction that client code cannot lock the Clipboard to discover
* its formats before requesting data in a particular format, while avoiding
* the overhead of fully rendering all data ahead of time.
*
* @author David Mendenhall
* @author Danila Sinopalnikov
*
* @since 1.4 (appeared in modified form as FullyRenderedTransferable in 1.3.1)
*/
public class ClipboardTransferable implements Transferable {
private final HashMap flavorsToData = new HashMap();
private DataFlavor[] flavors = new DataFlavor[0];
private final class DataFactory {
final long format;
final byte[] data;
DataFactory(long format, byte[] data) {
this.format = format;
this.data = data;
}
public Object getTransferData(DataFlavor flavor) throws IOException {
return DataTransferer.getInstance().
translateBytes(data, flavor, format,
ClipboardTransferable.this);
}
}
public ClipboardTransferable(SunClipboard clipboard) {
clipboard.openClipboard(null);
try {
long[] formats = clipboard.getClipboardFormats();
if (formats != null && formats.length > 0) {
// Since the SystemFlavorMap will specify many DataFlavors
// which map to the same format, we should cache data as we
// read it.
HashMap cached_data = new HashMap(formats.length, 1.0f);
Map flavorsForFormats = DataTransferer.getInstance().
getFlavorsForFormats(formats, SunClipboard.getDefaultFlavorTable());
for (Iterator iter = flavorsForFormats.keySet().iterator();
iter.hasNext(); )
{
DataFlavor flavor = (DataFlavor)iter.next();
Long lFormat = (Long)flavorsForFormats.get(flavor);
fetchOneFlavor(clipboard, flavor, lFormat, cached_data);
}
flavors = DataTransferer.getInstance().
setToSortedDataFlavorArray(flavorsToData.keySet());
}
} finally {
clipboard.closeClipboard();
}
}
private boolean fetchOneFlavor(SunClipboard clipboard, DataFlavor flavor,
Long lFormat, HashMap cached_data)
{
if (!flavorsToData.containsKey(flavor)) {
long format = lFormat.longValue();
Object data = null;
if (!cached_data.containsKey(lFormat)) {
try {
data = clipboard.getClipboardData(format);
} catch (IOException e) {
data = e;
} catch (Throwable e) {
e.printStackTrace();
}
// Cache this data, even if it's null, so we don't have to go
// to native code again for this format.
cached_data.put(lFormat, data);
} else {
data = cached_data.get(lFormat);
}
// Casting IOException to byte array causes ClassCastException.
// We should handle IOException separately - do not wrap them into
// DataFactory and report failure.
if (data instanceof IOException) {
flavorsToData.put(flavor, data);
return false;
} else if (data != null) {
flavorsToData.put(flavor, new DataFactory(format,
(byte[])data));
return true;
}
}
return false;
}
public DataFlavor[] getTransferDataFlavors() {
return (DataFlavor[])flavors.clone();
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavorsToData.containsKey(flavor);
}
public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException, IOException
{
if (!isDataFlavorSupported(flavor)) {
throw new UnsupportedFlavorException(flavor);
}
Object ret = flavorsToData.get(flavor);
if (ret instanceof IOException) {
// rethrow IOExceptions generated while fetching data
throw (IOException)ret;
} else if (ret instanceof DataFactory) {
// Now we can render the data
DataFactory factory = (DataFactory)ret;
ret = factory.getTransferData(flavor);
}
return ret;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,468 @@
/*
* Copyright (c) 1999, 2015, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.datatransfer;
import java.awt.EventQueue;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.FlavorTable;
import java.awt.datatransfer.SystemFlavorMap;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.FlavorListener;
import java.awt.datatransfer.FlavorEvent;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Set;
import java.util.HashSet;
import java.io.IOException;
import sun.awt.AppContext;
import sun.awt.PeerEvent;
import sun.awt.SunToolkit;
import sun.awt.EventListenerAggregate;
/**
* Serves as a common, helper superclass for the Win32 and X11 system
* Clipboards.
*
* @author Danila Sinopalnikov
* @author Alexander Gerasimov
*
* @since 1.3
*/
public abstract class SunClipboard extends Clipboard
implements PropertyChangeListener {
private AppContext contentsContext = null;
private final Object CLIPBOARD_FLAVOR_LISTENER_KEY;
/**
* A number of <code>FlavorListener</code>s currently registered
* on this clipboard across all <code>AppContext</code>s.
*/
private volatile int numberOfFlavorListeners = 0;
/**
* A set of {@code DataFlavor}s that is available on this clipboard. It is
* used for tracking changes of {@code DataFlavor}s available on this
* clipboard. Can be {@code null}.
*/
private volatile long[] currentFormats;
public SunClipboard(String name) {
super(name);
CLIPBOARD_FLAVOR_LISTENER_KEY = new StringBuffer(name + "_CLIPBOARD_FLAVOR_LISTENER_KEY");
}
public synchronized void setContents(Transferable contents,
ClipboardOwner owner) {
// 4378007 : Toolkit.getSystemClipboard().setContents(null, null)
// should throw NPE
if (contents == null) {
throw new NullPointerException("contents");
}
initContext();
final ClipboardOwner oldOwner = this.owner;
final Transferable oldContents = this.contents;
try {
this.owner = owner;
this.contents = new TransferableProxy(contents, true);
setContentsNative(contents);
} finally {
if (oldOwner != null && oldOwner != owner) {
EventQueue.invokeLater(new Runnable() {
public void run() {
oldOwner.lostOwnership(SunClipboard.this, oldContents);
}
});
}
}
}
private synchronized void initContext() {
final AppContext context = AppContext.getAppContext();
if (contentsContext != context) {
// Need to synchronize on the AppContext to guarantee that it cannot
// be disposed after the check, but before the listener is added.
synchronized (context) {
if (context.isDisposed()) {
throw new IllegalStateException("Can't set contents from disposed AppContext");
}
context.addPropertyChangeListener
(AppContext.DISPOSED_PROPERTY_NAME, this);
}
if (contentsContext != null) {
contentsContext.removePropertyChangeListener
(AppContext.DISPOSED_PROPERTY_NAME, this);
}
contentsContext = context;
}
}
public synchronized Transferable getContents(Object requestor) {
if (contents != null) {
return contents;
}
return new ClipboardTransferable(this);
}
/**
* @return the contents of this clipboard if it has been set from the same
* AppContext as it is currently retrieved or null otherwise
* @since 1.5
*/
protected synchronized Transferable getContextContents() {
AppContext context = AppContext.getAppContext();
return (context == contentsContext) ? contents : null;
}
/**
* @see java.awt.Clipboard#getAvailableDataFlavors
* @since 1.5
*/
public DataFlavor[] getAvailableDataFlavors() {
Transferable cntnts = getContextContents();
if (cntnts != null) {
return cntnts.getTransferDataFlavors();
}
long[] formats = getClipboardFormatsOpenClose();
return DataTransferer.getInstance().
getFlavorsForFormatsAsArray(formats, getDefaultFlavorTable());
}
/**
* @see java.awt.Clipboard#isDataFlavorAvailable
* @since 1.5
*/
public boolean isDataFlavorAvailable(DataFlavor flavor) {
if (flavor == null) {
throw new NullPointerException("flavor");
}
Transferable cntnts = getContextContents();
if (cntnts != null) {
return cntnts.isDataFlavorSupported(flavor);
}
long[] formats = getClipboardFormatsOpenClose();
return formatArrayAsDataFlavorSet(formats).contains(flavor);
}
/**
* @see java.awt.Clipboard#getData
* @since 1.5
*/
public Object getData(DataFlavor flavor)
throws UnsupportedFlavorException, IOException {
if (flavor == null) {
throw new NullPointerException("flavor");
}
Transferable cntnts = getContextContents();
if (cntnts != null) {
return cntnts.getTransferData(flavor);
}
long format = 0;
byte[] data = null;
Transferable localeTransferable = null;
try {
openClipboard(null);
long[] formats = getClipboardFormats();
Long lFormat = (Long)DataTransferer.getInstance().
getFlavorsForFormats(formats, getDefaultFlavorTable()).get(flavor);
if (lFormat == null) {
throw new UnsupportedFlavorException(flavor);
}
format = lFormat.longValue();
data = getClipboardData(format);
if (DataTransferer.getInstance().isLocaleDependentTextFormat(format)) {
localeTransferable = createLocaleTransferable(formats);
}
} finally {
closeClipboard();
}
return DataTransferer.getInstance().
translateBytes(data, flavor, format, localeTransferable);
}
/**
* The clipboard must be opened.
*
* @since 1.5
*/
protected Transferable createLocaleTransferable(long[] formats) throws IOException {
return null;
}
/**
* @throws IllegalStateException if the clipboard has not been opened
*/
public void openClipboard(SunClipboard newOwner) {}
public void closeClipboard() {}
public abstract long getID();
public void propertyChange(PropertyChangeEvent evt) {
if (AppContext.DISPOSED_PROPERTY_NAME.equals(evt.getPropertyName()) &&
Boolean.TRUE.equals(evt.getNewValue())) {
final AppContext disposedContext = (AppContext)evt.getSource();
lostOwnershipLater(disposedContext);
}
}
protected void lostOwnershipImpl() {
lostOwnershipLater(null);
}
/**
* Clears the clipboard state (contents, owner and contents context) and
* notifies the current owner that ownership is lost. Does nothing if the
* argument is not <code>null</code> and is not equal to the current
* contents context.
*
* @param disposedContext the AppContext that is disposed or
* <code>null</code> if the ownership is lost because another
* application acquired ownership.
*/
protected void lostOwnershipLater(final AppContext disposedContext) {
final AppContext context = this.contentsContext;
if (context == null) {
return;
}
SunToolkit.postEvent(context, new PeerEvent(this, () -> lostOwnershipNow(disposedContext),
PeerEvent.PRIORITY_EVENT));
}
protected void lostOwnershipNow(final AppContext disposedContext) {
final SunClipboard sunClipboard = SunClipboard.this;
ClipboardOwner owner = null;
Transferable contents = null;
synchronized (sunClipboard) {
final AppContext context = sunClipboard.contentsContext;
if (context == null) {
return;
}
if (disposedContext == null || context == disposedContext) {
owner = sunClipboard.owner;
contents = sunClipboard.contents;
sunClipboard.contentsContext = null;
sunClipboard.owner = null;
sunClipboard.contents = null;
sunClipboard.clearNativeContext();
context.removePropertyChangeListener
(AppContext.DISPOSED_PROPERTY_NAME, sunClipboard);
} else {
return;
}
}
if (owner != null) {
owner.lostOwnership(sunClipboard, contents);
}
}
protected abstract void clearNativeContext();
protected abstract void setContentsNative(Transferable contents);
/**
* @since 1.5
*/
protected long[] getClipboardFormatsOpenClose() {
try {
openClipboard(null);
return getClipboardFormats();
} finally {
closeClipboard();
}
}
/**
* Returns zero-length array (not null) if the number of available formats is zero.
*
* @throws IllegalStateException if formats could not be retrieved
*/
protected abstract long[] getClipboardFormats();
protected abstract byte[] getClipboardData(long format) throws IOException;
private static Set formatArrayAsDataFlavorSet(long[] formats) {
return (formats == null) ? null :
DataTransferer.getInstance().
getFlavorsForFormatsAsSet(formats, getDefaultFlavorTable());
}
public synchronized void addFlavorListener(FlavorListener listener) {
if (listener == null) {
return;
}
AppContext appContext = AppContext.getAppContext();
EventListenerAggregate contextFlavorListeners = (EventListenerAggregate)
appContext.get(CLIPBOARD_FLAVOR_LISTENER_KEY);
if (contextFlavorListeners == null) {
contextFlavorListeners = new EventListenerAggregate(FlavorListener.class);
appContext.put(CLIPBOARD_FLAVOR_LISTENER_KEY, contextFlavorListeners);
}
contextFlavorListeners.add(listener);
if (numberOfFlavorListeners++ == 0) {
long[] currentFormats = null;
try {
openClipboard(null);
currentFormats = getClipboardFormats();
} catch (final IllegalStateException ignored) {
} finally {
closeClipboard();
}
this.currentFormats = currentFormats;
registerClipboardViewerChecked();
}
}
public synchronized void removeFlavorListener(FlavorListener listener) {
if (listener == null) {
return;
}
AppContext appContext = AppContext.getAppContext();
EventListenerAggregate contextFlavorListeners = (EventListenerAggregate)
appContext.get(CLIPBOARD_FLAVOR_LISTENER_KEY);
if (contextFlavorListeners == null){
//else we throw NullPointerException, but it is forbidden
return;
}
if (contextFlavorListeners.remove(listener) &&
--numberOfFlavorListeners == 0) {
unregisterClipboardViewerChecked();
currentFormats = null;
}
}
public synchronized FlavorListener[] getFlavorListeners() {
EventListenerAggregate contextFlavorListeners = (EventListenerAggregate)
AppContext.getAppContext().get(CLIPBOARD_FLAVOR_LISTENER_KEY);
return contextFlavorListeners == null ? new FlavorListener[0] :
(FlavorListener[])contextFlavorListeners.getListenersCopy();
}
public boolean areFlavorListenersRegistered() {
return (numberOfFlavorListeners > 0);
}
protected abstract void registerClipboardViewerChecked();
protected abstract void unregisterClipboardViewerChecked();
/**
* Checks change of the <code>DataFlavor</code>s and, if necessary,
* posts notifications on <code>FlavorEvent</code>s to the
* AppContexts' EDTs.
* The parameter <code>formats</code> is null iff we have just
* failed to get formats available on the clipboard.
*
* @param formats data formats that have just been retrieved from
* this clipboard
*/
protected final void checkChange(final long[] formats) {
if (Arrays.equals(formats, currentFormats)) {
// we've been able to successfully get available on the clipboard
// DataFlavors this and previous time and they are coincident;
// don't notify
return;
}
currentFormats = formats;
class SunFlavorChangeNotifier implements Runnable {
private final FlavorListener flavorListener;
SunFlavorChangeNotifier(FlavorListener flavorListener) {
this.flavorListener = flavorListener;
}
public void run() {
if (flavorListener != null) {
flavorListener.flavorsChanged(new FlavorEvent(SunClipboard.this));
}
}
};
for (Iterator it = AppContext.getAppContexts().iterator(); it.hasNext();) {
AppContext appContext = (AppContext)it.next();
if (appContext == null || appContext.isDisposed()) {
continue;
}
EventListenerAggregate flavorListeners = (EventListenerAggregate)
appContext.get(CLIPBOARD_FLAVOR_LISTENER_KEY);
if (flavorListeners != null) {
FlavorListener[] flavorListenerArray =
(FlavorListener[])flavorListeners.getListenersInternal();
for (int i = 0; i < flavorListenerArray.length; i++) {
SunToolkit.postEvent(appContext, new PeerEvent(this,
new SunFlavorChangeNotifier(flavorListenerArray[i]),
PeerEvent.PRIORITY_EVENT));
}
}
}
}
public static FlavorTable getDefaultFlavorTable() {
return (FlavorTable) SystemFlavorMap.getDefaultFlavorMap();
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) 2000, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.datatransfer;
public interface ToolkitThreadBlockedHandler {
public void lock();
public void unlock();
public void enter();
public void exit();
}

View File

@@ -0,0 +1,218 @@
/*
* Copyright (c) 2000, 2013, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.datatransfer;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.OutputStream;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Proxies for another Transferable so that Serializable objects are never
* returned directly by DnD or the Clipboard. Instead, a new instance of the
* object is returned.
*
* @author Lawrence P.G. Cable
* @author David Mendenhall
*
* @since 1.4
*/
public class TransferableProxy implements Transferable {
public TransferableProxy(Transferable t, boolean local) {
transferable = t;
isLocal = local;
}
public DataFlavor[] getTransferDataFlavors() {
return transferable.getTransferDataFlavors();
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
return transferable.isDataFlavorSupported(flavor);
}
public Object getTransferData(DataFlavor df)
throws UnsupportedFlavorException, IOException
{
Object data = transferable.getTransferData(df);
// If the data is a Serializable object, then create a new instance
// before returning it. This insulates applications sharing DnD and
// Clipboard data from each other.
if (data != null && isLocal && df.isFlavorSerializedObjectType()) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ClassLoaderObjectOutputStream oos =
new ClassLoaderObjectOutputStream(baos);
oos.writeObject(data);
ByteArrayInputStream bais =
new ByteArrayInputStream(baos.toByteArray());
try {
ClassLoaderObjectInputStream ois =
new ClassLoaderObjectInputStream(bais,
oos.getClassLoaderMap());
data = ois.readObject();
} catch (ClassNotFoundException cnfe) {
throw (IOException)new IOException().initCause(cnfe);
}
}
return data;
}
protected final Transferable transferable;
protected final boolean isLocal;
}
final class ClassLoaderObjectOutputStream extends ObjectOutputStream {
private final Map<Set<String>, ClassLoader> map =
new HashMap<Set<String>, ClassLoader>();
ClassLoaderObjectOutputStream(OutputStream os) throws IOException {
super(os);
}
protected void annotateClass(final Class<?> cl) throws IOException {
ClassLoader classLoader =
(ClassLoader)AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return cl.getClassLoader();
}
});
Set<String> s = new HashSet<String>(1);
s.add(cl.getName());
map.put(s, classLoader);
}
protected void annotateProxyClass(final Class<?> cl) throws IOException {
ClassLoader classLoader =
(ClassLoader)AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return cl.getClassLoader();
}
});
Class[] interfaces = cl.getInterfaces();
Set<String> s = new HashSet<String>(interfaces.length);
for (int i = 0; i < interfaces.length; i++) {
s.add(interfaces[i].getName());
}
map.put(s, classLoader);
}
Map<Set<String>, ClassLoader> getClassLoaderMap() {
return new HashMap(map);
}
}
final class ClassLoaderObjectInputStream extends ObjectInputStream {
private final Map<Set<String>, ClassLoader> map;
ClassLoaderObjectInputStream(InputStream is,
Map<Set<String>, ClassLoader> map)
throws IOException {
super(is);
if (map == null) {
throw new NullPointerException("Null map");
}
this.map = map;
}
protected Class<?> resolveClass(ObjectStreamClass classDesc)
throws IOException, ClassNotFoundException {
String className = classDesc.getName();
Set<String> s = new HashSet<String>(1);
s.add(className);
ClassLoader classLoader = map.get(s);
if (classLoader != null) {
return Class.forName(className, false, classLoader);
} else {
return super.resolveClass(classDesc);
}
}
protected Class<?> resolveProxyClass(String[] interfaces)
throws IOException, ClassNotFoundException {
Set<String> s = new HashSet<String>(interfaces.length);
for (int i = 0; i < interfaces.length; i++) {
s.add(interfaces[i]);
}
ClassLoader classLoader = map.get(s);
if (classLoader == null) {
return super.resolveProxyClass(interfaces);
}
// The code below is mostly copied from the superclass.
ClassLoader nonPublicLoader = null;
boolean hasNonPublicInterface = false;
// define proxy in class loader of non-public interface(s), if any
Class[] classObjs = new Class[interfaces.length];
for (int i = 0; i < interfaces.length; i++) {
Class cl = Class.forName(interfaces[i], false, classLoader);
if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
if (hasNonPublicInterface) {
if (nonPublicLoader != cl.getClassLoader()) {
throw new IllegalAccessError(
"conflicting non-public interface class loaders");
}
} else {
nonPublicLoader = cl.getClassLoader();
hasNonPublicInterface = true;
}
}
classObjs[i] = cl;
}
try {
return Proxy.getProxyClass(hasNonPublicInterface ?
nonPublicLoader : classLoader,
classObjs);
} catch (IllegalArgumentException e) {
throw new ClassNotFoundException(null, e);
}
}
}

View File

@@ -0,0 +1,502 @@
/*
* Copyright (c) 2000, 2013, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.dnd;
import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.EventQueue;
import java.awt.Image;
import java.awt.Point;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragSourceContext;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.InvalidDnDOperationException;
import java.awt.dnd.peer.DragSourceContextPeer;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.util.Map;
import java.util.SortedMap;
import sun.awt.SunToolkit;
import sun.awt.datatransfer.DataTransferer;
import java.awt.datatransfer.DataFlavor;
/**
* <p>
* TBC
* </p>
*
* @since JDK1.3.1
*
*/
public abstract class SunDragSourceContextPeer implements DragSourceContextPeer {
private DragGestureEvent trigger;
private Component component;
private Cursor cursor;
private Image dragImage;
private Point dragImageOffset;
private long nativeCtxt;
private DragSourceContext dragSourceContext;
private int sourceActions;
private static boolean dragDropInProgress = false;
private static boolean discardingMouseEvents = false;
/*
* dispatch constants
*/
protected final static int DISPATCH_ENTER = 1;
protected final static int DISPATCH_MOTION = 2;
protected final static int DISPATCH_CHANGED = 3;
protected final static int DISPATCH_EXIT = 4;
protected final static int DISPATCH_FINISH = 5;
protected final static int DISPATCH_MOUSE_MOVED = 6;
/**
* construct a new SunDragSourceContextPeer
*/
public SunDragSourceContextPeer(DragGestureEvent dge) {
trigger = dge;
if (trigger != null) {
component = trigger.getComponent();
} else {
component = null;
}
}
/**
* Synchro messages in AWT
*/
public void startSecondaryEventLoop(){}
public void quitSecondaryEventLoop(){}
/**
* initiate a DnD operation ...
*/
public void startDrag(DragSourceContext dsc, Cursor c, Image di, Point p)
throws InvalidDnDOperationException {
/* Fix for 4354044: don't initiate a drag if event sequence provided by
* DragGestureRecognizer is empty */
if (getTrigger().getTriggerEvent() == null) {
throw new InvalidDnDOperationException("DragGestureEvent has a null trigger");
}
dragSourceContext = dsc;
cursor = c;
sourceActions = getDragSourceContext().getSourceActions();
dragImage = di;
dragImageOffset = p;
Transferable transferable = getDragSourceContext().getTransferable();
SortedMap<Long,DataFlavor> formatMap = DataTransferer.getInstance().
getFormatsForTransferable(transferable, DataTransferer.adaptFlavorMap
(getTrigger().getDragSource().getFlavorMap()));
long[] formats = DataTransferer.getInstance().
keysToLongArray(formatMap);
startDrag(transferable, formats, formatMap);
/*
* Fix for 4613903.
* Filter out all mouse events that are currently on the event queue.
*/
discardingMouseEvents = true;
EventQueue.invokeLater(new Runnable() {
public void run() {
discardingMouseEvents = false;
}
});
}
protected abstract void startDrag(Transferable trans,
long[] formats, Map formatMap);
/**
* set cursor
*/
public void setCursor(Cursor c) throws InvalidDnDOperationException {
synchronized (this) {
if (cursor == null || !cursor.equals(c)) {
cursor = c;
// NOTE: native context can be null at this point.
// setNativeCursor() should handle it properly.
setNativeCursor(getNativeContext(), c,
c != null ? c.getType() : 0);
}
}
}
/**
* return cursor
*/
public Cursor getCursor() {
return cursor;
}
/**
* Returns the drag image. If there is no image to drag,
* the returned value is {@code null}
*
* @return the reference to the drag image
*/
public Image getDragImage() {
return dragImage;
}
/**
* Returns an anchor offset for the image to drag.
*
* @return a {@code Point} object that corresponds
* to coordinates of an anchor offset of the image
* relative to the upper left corner of the image.
* The point {@code (0,0)} returns by default.
*/
public Point getDragImageOffset() {
if (dragImageOffset == null) {
return new Point(0,0);
}
return new Point(dragImageOffset);
}
/**
* downcall into native code
*/
protected abstract void setNativeCursor(long nativeCtxt, Cursor c,
int cType);
protected synchronized void setTrigger(DragGestureEvent dge) {
trigger = dge;
if (trigger != null) {
component = trigger.getComponent();
} else {
component = null;
}
}
protected DragGestureEvent getTrigger() {
return trigger;
}
protected Component getComponent() {
return component;
}
protected synchronized void setNativeContext(long ctxt) {
nativeCtxt = ctxt;
}
protected synchronized long getNativeContext() {
return nativeCtxt;
}
protected DragSourceContext getDragSourceContext() {
return dragSourceContext;
}
/**
* Notify the peer that the transferables' DataFlavors have changed.
*
* No longer useful as the transferables are determined at the time
* of the drag.
*/
public void transferablesFlavorsChanged() {
}
protected final void postDragSourceDragEvent(final int targetAction,
final int modifiers,
final int x, final int y,
final int dispatchType) {
final int dropAction =
SunDragSourceContextPeer.convertModifiersToDropAction(modifiers,
sourceActions);
DragSourceDragEvent event =
new DragSourceDragEvent(getDragSourceContext(),
dropAction,
targetAction & sourceActions,
modifiers, x, y);
EventDispatcher dispatcher = new EventDispatcher(dispatchType, event);
SunToolkit.invokeLaterOnAppContext(
SunToolkit.targetToAppContext(getComponent()), dispatcher);
startSecondaryEventLoop();
}
/**
* upcall from native code
*/
protected void dragEnter(final int targetActions,
final int modifiers,
final int x, final int y) {
postDragSourceDragEvent(targetActions, modifiers, x, y, DISPATCH_ENTER);
}
/**
* upcall from native code
*/
private void dragMotion(final int targetActions,
final int modifiers,
final int x, final int y) {
postDragSourceDragEvent(targetActions, modifiers, x, y, DISPATCH_MOTION);
}
/**
* upcall from native code
*/
private void operationChanged(final int targetActions,
final int modifiers,
final int x, final int y) {
postDragSourceDragEvent(targetActions, modifiers, x, y, DISPATCH_CHANGED);
}
/**
* upcall from native code
*/
protected final void dragExit(final int x, final int y) {
DragSourceEvent event =
new DragSourceEvent(getDragSourceContext(), x, y);
EventDispatcher dispatcher =
new EventDispatcher(DISPATCH_EXIT, event);
SunToolkit.invokeLaterOnAppContext(
SunToolkit.targetToAppContext(getComponent()), dispatcher);
startSecondaryEventLoop();
}
/**
* upcall from native code
*/
private void dragMouseMoved(final int targetActions,
final int modifiers,
final int x, final int y) {
postDragSourceDragEvent(targetActions, modifiers, x, y,
DISPATCH_MOUSE_MOVED);
}
/**
* upcall from native code via implemented class (do)
*/
protected final void dragDropFinished(final boolean success,
final int operations,
final int x, final int y) {
DragSourceEvent event =
new DragSourceDropEvent(getDragSourceContext(),
operations & sourceActions,
success, x, y);
EventDispatcher dispatcher =
new EventDispatcher(DISPATCH_FINISH, event);
SunToolkit.invokeLaterOnAppContext(
SunToolkit.targetToAppContext(getComponent()), dispatcher);
startSecondaryEventLoop();
setNativeContext(0);
dragImage = null;
dragImageOffset = null;
}
public static void setDragDropInProgress(boolean b)
throws InvalidDnDOperationException {
synchronized (SunDragSourceContextPeer.class) {
if (dragDropInProgress == b) {
throw new InvalidDnDOperationException(getExceptionMessage(b));
}
dragDropInProgress = b;
}
}
/**
* Filters out all mouse events that were on the java event queue when
* startDrag was called.
*/
public static boolean checkEvent(AWTEvent event) {
if (discardingMouseEvents && event instanceof MouseEvent) {
MouseEvent mouseEvent = (MouseEvent)event;
if (!(mouseEvent instanceof SunDropTargetEvent)) {
return false;
}
}
return true;
}
public static void checkDragDropInProgress()
throws InvalidDnDOperationException {
if (dragDropInProgress) {
throw new InvalidDnDOperationException(getExceptionMessage(true));
}
}
private static String getExceptionMessage(boolean b) {
return b ? "Drag and drop in progress" : "No drag in progress";
}
public static int convertModifiersToDropAction(final int modifiers,
final int supportedActions) {
int dropAction = DnDConstants.ACTION_NONE;
/*
* Fix for 4285634.
* Calculate the drop action to match Motif DnD behavior.
* If the user selects an operation (by pressing a modifier key),
* return the selected operation or ACTION_NONE if the selected
* operation is not supported by the drag source.
* If the user doesn't select an operation search the set of operations
* supported by the drag source for ACTION_MOVE, then for
* ACTION_COPY, then for ACTION_LINK and return the first operation
* found.
*/
switch (modifiers & (InputEvent.SHIFT_DOWN_MASK |
InputEvent.CTRL_DOWN_MASK)) {
case InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK:
dropAction = DnDConstants.ACTION_LINK; break;
case InputEvent.CTRL_DOWN_MASK:
dropAction = DnDConstants.ACTION_COPY; break;
case InputEvent.SHIFT_DOWN_MASK:
dropAction = DnDConstants.ACTION_MOVE; break;
default:
if ((supportedActions & DnDConstants.ACTION_MOVE) != 0) {
dropAction = DnDConstants.ACTION_MOVE;
} else if ((supportedActions & DnDConstants.ACTION_COPY) != 0) {
dropAction = DnDConstants.ACTION_COPY;
} else if ((supportedActions & DnDConstants.ACTION_LINK) != 0) {
dropAction = DnDConstants.ACTION_LINK;
}
}
return dropAction & supportedActions;
}
private void cleanup() {
trigger = null;
component = null;
cursor = null;
dragSourceContext = null;
SunDropTargetContextPeer.setCurrentJVMLocalSourceTransferable(null);
SunDragSourceContextPeer.setDragDropInProgress(false);
}
private class EventDispatcher implements Runnable {
private final int dispatchType;
private final DragSourceEvent event;
EventDispatcher(int dispatchType, DragSourceEvent event) {
switch (dispatchType) {
case DISPATCH_ENTER:
case DISPATCH_MOTION:
case DISPATCH_CHANGED:
case DISPATCH_MOUSE_MOVED:
if (!(event instanceof DragSourceDragEvent)) {
throw new IllegalArgumentException("Event: " + event);
}
break;
case DISPATCH_EXIT:
break;
case DISPATCH_FINISH:
if (!(event instanceof DragSourceDropEvent)) {
throw new IllegalArgumentException("Event: " + event);
}
break;
default:
throw new IllegalArgumentException("Dispatch type: " +
dispatchType);
}
this.dispatchType = dispatchType;
this.event = event;
}
public void run() {
DragSourceContext dragSourceContext =
SunDragSourceContextPeer.this.getDragSourceContext();
try {
switch (dispatchType) {
case DISPATCH_ENTER:
dragSourceContext.dragEnter((DragSourceDragEvent)event);
break;
case DISPATCH_MOTION:
dragSourceContext.dragOver((DragSourceDragEvent)event);
break;
case DISPATCH_CHANGED:
dragSourceContext.dropActionChanged((DragSourceDragEvent)event);
break;
case DISPATCH_EXIT:
dragSourceContext.dragExit(event);
break;
case DISPATCH_MOUSE_MOVED:
dragSourceContext.dragMouseMoved((DragSourceDragEvent)event);
break;
case DISPATCH_FINISH:
try {
dragSourceContext.dragDropEnd((DragSourceDropEvent)event);
} finally {
SunDragSourceContextPeer.this.cleanup();
}
break;
default:
throw new IllegalStateException("Dispatch type: " +
dispatchType);
}
} finally {
SunDragSourceContextPeer.this.quitSecondaryEventLoop();
}
}
}
}

View File

@@ -0,0 +1,925 @@
/*
* Copyright (c) 2000, 2014, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.dnd;
import java.awt.Component;
import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetContext;
import java.awt.dnd.DropTargetListener;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.InvalidDnDOperationException;
import java.awt.dnd.peer.DropTargetContextPeer;
import java.util.HashSet;
import java.util.Map;
import java.util.Arrays;
import sun.util.logging.PlatformLogger;
import java.io.IOException;
import java.io.InputStream;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
import sun.awt.datatransfer.DataTransferer;
import sun.awt.datatransfer.ToolkitThreadBlockedHandler;
import sun.security.util.SecurityConstants;
/**
* <p>
* The SunDropTargetContextPeer class is the generic class responsible for handling
* the interaction between a windowing systems DnD system and Java.
* </p>
*
* @since JDK1.3.1
*
*/
public abstract class SunDropTargetContextPeer implements DropTargetContextPeer, Transferable {
/*
* A boolean constant that requires the peer to wait until the
* SunDropTargetEvent is processed and return the status back
* to the native code.
*/
public static final boolean DISPATCH_SYNC = true;
private DropTarget currentDT;
private DropTargetContext currentDTC;
private long[] currentT;
private int currentA; // target actions
private int currentSA; // source actions
private int currentDA; // current drop action
private int previousDA;
private long nativeDragContext;
private Transferable local;
private boolean dragRejected = false;
protected int dropStatus = STATUS_NONE;
protected boolean dropComplete = false;
// The flag is used to monitor whether the drop action is
// handled by a user. That allows to distinct during
// which operation getTransferData() method is invoked.
boolean dropInProcess = false;
/*
* global lock
*/
protected static final Object _globalLock = new Object();
private static final PlatformLogger dndLog = PlatformLogger.getLogger("sun.awt.dnd.SunDropTargetContextPeer");
/*
* a primitive mechanism for advertising intra-JVM Transferables
*/
protected static Transferable currentJVMLocalSourceTransferable = null;
public static void setCurrentJVMLocalSourceTransferable(Transferable t) throws InvalidDnDOperationException {
synchronized(_globalLock) {
if (t != null && currentJVMLocalSourceTransferable != null) {
throw new InvalidDnDOperationException();
} else {
currentJVMLocalSourceTransferable = t;
}
}
}
/**
* obtain the transferable iff the operation is in the same VM
*/
private static Transferable getJVMLocalSourceTransferable() {
return currentJVMLocalSourceTransferable;
}
/*
* constants used by dropAccept() or dropReject()
*/
protected final static int STATUS_NONE = 0; // none pending
protected final static int STATUS_WAIT = 1; // drop pending
protected final static int STATUS_ACCEPT = 2;
protected final static int STATUS_REJECT = -1;
/**
* create the peer
*/
public SunDropTargetContextPeer() {
super();
}
/**
* @return the DropTarget associated with this peer
*/
public DropTarget getDropTarget() { return currentDT; }
/**
* @param actions set the current actions
*/
public synchronized void setTargetActions(int actions) {
currentA = actions &
(DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK);
}
/**
* @return the current target actions
*/
public int getTargetActions() {
return currentA;
}
/**
* get the Transferable associated with the drop
*/
public Transferable getTransferable() {
return this;
}
/**
* @return current DataFlavors available
*/
// NOTE: This method may be called by privileged threads.
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
public DataFlavor[] getTransferDataFlavors() {
final Transferable localTransferable = local;
if (localTransferable != null) {
return localTransferable.getTransferDataFlavors();
} else {
return DataTransferer.getInstance().getFlavorsForFormatsAsArray
(currentT, DataTransferer.adaptFlavorMap
(currentDT.getFlavorMap()));
}
}
/**
* @return if the flavor is supported
*/
public boolean isDataFlavorSupported(DataFlavor df) {
Transferable localTransferable = local;
if (localTransferable != null) {
return localTransferable.isDataFlavorSupported(df);
} else {
return DataTransferer.getInstance().getFlavorsForFormats
(currentT, DataTransferer.adaptFlavorMap
(currentDT.getFlavorMap())).
containsKey(df);
}
}
/**
* @return the data
*/
public Object getTransferData(DataFlavor df)
throws UnsupportedFlavorException, IOException,
InvalidDnDOperationException
{
SecurityManager sm = System.getSecurityManager();
try {
if (!dropInProcess && sm != null) {
sm.checkPermission(SecurityConstants.AWT.ACCESS_CLIPBOARD_PERMISSION);
}
} catch (Exception e) {
Thread currentThread = Thread.currentThread();
currentThread.getUncaughtExceptionHandler().uncaughtException(currentThread, e);
return null;
}
Long lFormat = null;
Transferable localTransferable = local;
if (localTransferable != null) {
return localTransferable.getTransferData(df);
}
if (dropStatus != STATUS_ACCEPT || dropComplete) {
throw new InvalidDnDOperationException("No drop current");
}
Map flavorMap = DataTransferer.getInstance().getFlavorsForFormats
(currentT, DataTransferer.adaptFlavorMap
(currentDT.getFlavorMap()));
lFormat = (Long)flavorMap.get(df);
if (lFormat == null) {
throw new UnsupportedFlavorException(df);
}
if (df.isRepresentationClassRemote() &&
currentDA != DnDConstants.ACTION_LINK) {
throw new InvalidDnDOperationException("only ACTION_LINK is permissable for transfer of java.rmi.Remote objects");
}
final long format = lFormat.longValue();
Object ret = getNativeData(format);
if (ret instanceof byte[]) {
try {
return DataTransferer.getInstance().
translateBytes((byte[])ret, df, format, this);
} catch (IOException e) {
throw new InvalidDnDOperationException(e.getMessage());
}
} else if (ret instanceof InputStream) {
try {
return DataTransferer.getInstance().
translateStream((InputStream)ret, df, format, this);
} catch (IOException e) {
throw new InvalidDnDOperationException(e.getMessage());
}
} else {
throw new IOException("no native data was transfered");
}
}
protected abstract Object getNativeData(long format)
throws IOException;
/**
* @return if the transfer is a local one
*/
public boolean isTransferableJVMLocal() {
return local != null || getJVMLocalSourceTransferable() != null;
}
private int handleEnterMessage(final Component component,
final int x, final int y,
final int dropAction,
final int actions, final long[] formats,
final long nativeCtxt) {
return postDropTargetEvent(component, x, y, dropAction, actions,
formats, nativeCtxt,
SunDropTargetEvent.MOUSE_ENTERED,
SunDropTargetContextPeer.DISPATCH_SYNC);
}
/**
* actual processing on EventQueue Thread
*/
protected void processEnterMessage(SunDropTargetEvent event) {
Component c = (Component)event.getSource();
DropTarget dt = c.getDropTarget();
Point hots = event.getPoint();
local = getJVMLocalSourceTransferable();
if (currentDTC != null) { // some wreckage from last time
currentDTC.removeNotify();
currentDTC = null;
}
if (c.isShowing() && dt != null && dt.isActive()) {
currentDT = dt;
currentDTC = currentDT.getDropTargetContext();
currentDTC.addNotify(this);
currentA = dt.getDefaultActions();
try {
((DropTargetListener)dt).dragEnter(new DropTargetDragEvent(currentDTC,
hots,
currentDA,
currentSA));
} catch (Exception e) {
e.printStackTrace();
currentDA = DnDConstants.ACTION_NONE;
}
} else {
currentDT = null;
currentDTC = null;
currentDA = DnDConstants.ACTION_NONE;
currentSA = DnDConstants.ACTION_NONE;
currentA = DnDConstants.ACTION_NONE;
}
}
/**
* upcall to handle exit messages
*/
private void handleExitMessage(final Component component,
final long nativeCtxt) {
/*
* Even though the return value is irrelevant for this event, it is
* dispatched synchronously to fix 4393148 properly.
*/
postDropTargetEvent(component, 0, 0, DnDConstants.ACTION_NONE,
DnDConstants.ACTION_NONE, null, nativeCtxt,
SunDropTargetEvent.MOUSE_EXITED,
SunDropTargetContextPeer.DISPATCH_SYNC);
}
/**
*
*/
protected void processExitMessage(SunDropTargetEvent event) {
Component c = (Component)event.getSource();
DropTarget dt = c.getDropTarget();
DropTargetContext dtc = null;
if (dt == null) {
currentDT = null;
currentT = null;
if (currentDTC != null) {
currentDTC.removeNotify();
}
currentDTC = null;
return;
}
if (dt != currentDT) {
if (currentDTC != null) {
currentDTC.removeNotify();
}
currentDT = dt;
currentDTC = dt.getDropTargetContext();
currentDTC.addNotify(this);
}
dtc = currentDTC;
if (dt.isActive()) try {
((DropTargetListener)dt).dragExit(new DropTargetEvent(dtc));
} catch (Exception e) {
e.printStackTrace();
} finally {
currentA = DnDConstants.ACTION_NONE;
currentSA = DnDConstants.ACTION_NONE;
currentDA = DnDConstants.ACTION_NONE;
currentDT = null;
currentT = null;
currentDTC.removeNotify();
currentDTC = null;
local = null;
dragRejected = false;
}
}
private int handleMotionMessage(final Component component,
final int x, final int y,
final int dropAction,
final int actions, final long[] formats,
final long nativeCtxt) {
return postDropTargetEvent(component, x, y, dropAction, actions,
formats, nativeCtxt,
SunDropTargetEvent.MOUSE_DRAGGED,
SunDropTargetContextPeer.DISPATCH_SYNC);
}
/**
*
*/
protected void processMotionMessage(SunDropTargetEvent event,
boolean operationChanged) {
Component c = (Component)event.getSource();
Point hots = event.getPoint();
int id = event.getID();
DropTarget dt = c.getDropTarget();
DropTargetContext dtc = null;
if (c.isShowing() && (dt != null) && dt.isActive()) {
if (currentDT != dt) {
if (currentDTC != null) {
currentDTC.removeNotify();
}
currentDT = dt;
currentDTC = null;
}
dtc = currentDT.getDropTargetContext();
if (dtc != currentDTC) {
if (currentDTC != null) {
currentDTC.removeNotify();
}
currentDTC = dtc;
currentDTC.addNotify(this);
}
currentA = currentDT.getDefaultActions();
try {
DropTargetDragEvent dtde = new DropTargetDragEvent(dtc,
hots,
currentDA,
currentSA);
DropTargetListener dtl = (DropTargetListener)dt;
if (operationChanged) {
dtl.dropActionChanged(dtde);
} else {
dtl.dragOver(dtde);
}
if (dragRejected) {
currentDA = DnDConstants.ACTION_NONE;
}
} catch (Exception e) {
e.printStackTrace();
currentDA = DnDConstants.ACTION_NONE;
}
} else {
currentDA = DnDConstants.ACTION_NONE;
}
}
/**
* upcall to handle the Drop message
*/
private void handleDropMessage(final Component component,
final int x, final int y,
final int dropAction, final int actions,
final long[] formats,
final long nativeCtxt) {
postDropTargetEvent(component, x, y, dropAction, actions,
formats, nativeCtxt,
SunDropTargetEvent.MOUSE_DROPPED,
!SunDropTargetContextPeer.DISPATCH_SYNC);
}
/**
*
*/
protected void processDropMessage(SunDropTargetEvent event) {
Component c = (Component)event.getSource();
Point hots = event.getPoint();
DropTarget dt = c.getDropTarget();
dropStatus = STATUS_WAIT; // drop pending ACK
dropComplete = false;
if (c.isShowing() && dt != null && dt.isActive()) {
DropTargetContext dtc = dt.getDropTargetContext();
currentDT = dt;
if (currentDTC != null) {
currentDTC.removeNotify();
}
currentDTC = dtc;
currentDTC.addNotify(this);
currentA = dt.getDefaultActions();
synchronized(_globalLock) {
if ((local = getJVMLocalSourceTransferable()) != null)
setCurrentJVMLocalSourceTransferable(null);
}
dropInProcess = true;
try {
((DropTargetListener)dt).drop(new DropTargetDropEvent(dtc,
hots,
currentDA,
currentSA,
local != null));
} finally {
if (dropStatus == STATUS_WAIT) {
rejectDrop();
} else if (dropComplete == false) {
dropComplete(false);
}
dropInProcess = false;
}
} else {
rejectDrop();
}
}
protected int postDropTargetEvent(final Component component,
final int x, final int y,
final int dropAction,
final int actions,
final long[] formats,
final long nativeCtxt,
final int eventID,
final boolean dispatchType) {
AppContext appContext = SunToolkit.targetToAppContext(component);
EventDispatcher dispatcher =
new EventDispatcher(this, dropAction, actions, formats, nativeCtxt,
dispatchType);
SunDropTargetEvent event =
new SunDropTargetEvent(component, eventID, x, y, dispatcher);
if (dispatchType == SunDropTargetContextPeer.DISPATCH_SYNC) {
DataTransferer.getInstance().getToolkitThreadBlockedHandler().lock();
}
// schedule callback
SunToolkit.postEvent(appContext, event);
eventPosted(event);
if (dispatchType == SunDropTargetContextPeer.DISPATCH_SYNC) {
while (!dispatcher.isDone()) {
DataTransferer.getInstance().getToolkitThreadBlockedHandler().enter();
}
DataTransferer.getInstance().getToolkitThreadBlockedHandler().unlock();
// return target's response
return dispatcher.getReturnValue();
} else {
return 0;
}
}
/**
* acceptDrag
*/
public synchronized void acceptDrag(int dragOperation) {
if (currentDT == null) {
throw new InvalidDnDOperationException("No Drag pending");
}
currentDA = mapOperation(dragOperation);
if (currentDA != DnDConstants.ACTION_NONE) {
dragRejected = false;
}
}
/**
* rejectDrag
*/
public synchronized void rejectDrag() {
if (currentDT == null) {
throw new InvalidDnDOperationException("No Drag pending");
}
currentDA = DnDConstants.ACTION_NONE;
dragRejected = true;
}
/**
* acceptDrop
*/
public synchronized void acceptDrop(int dropOperation) {
if (dropOperation == DnDConstants.ACTION_NONE)
throw new IllegalArgumentException("invalid acceptDrop() action");
if (dropStatus == STATUS_WAIT || dropStatus == STATUS_ACCEPT) {
currentDA = currentA = mapOperation(dropOperation & currentSA);
dropStatus = STATUS_ACCEPT;
dropComplete = false;
} else {
throw new InvalidDnDOperationException("invalid acceptDrop()");
}
}
/**
* reject Drop
*/
public synchronized void rejectDrop() {
if (dropStatus != STATUS_WAIT) {
throw new InvalidDnDOperationException("invalid rejectDrop()");
}
dropStatus = STATUS_REJECT;
/*
* Fix for 4285634.
* The target rejected the drop means that it doesn't perform any
* drop action. This change is to make Solaris behavior consistent
* with Win32.
*/
currentDA = DnDConstants.ACTION_NONE;
dropComplete(false);
}
/**
* mapOperation
*/
private int mapOperation(int operation) {
int[] operations = {
DnDConstants.ACTION_MOVE,
DnDConstants.ACTION_COPY,
DnDConstants.ACTION_LINK,
};
int ret = DnDConstants.ACTION_NONE;
for (int i = 0; i < operations.length; i++) {
if ((operation & operations[i]) == operations[i]) {
ret = operations[i];
break;
}
}
return ret;
}
/**
* signal drop complete
*/
public synchronized void dropComplete(boolean success) {
if (dropStatus == STATUS_NONE) {
throw new InvalidDnDOperationException("No Drop pending");
}
if (currentDTC != null) currentDTC.removeNotify();
currentDT = null;
currentDTC = null;
currentT = null;
currentA = DnDConstants.ACTION_NONE;
synchronized(_globalLock) {
currentJVMLocalSourceTransferable = null;
}
dropStatus = STATUS_NONE;
dropComplete = true;
try {
doDropDone(success, currentDA, local != null);
} finally {
currentDA = DnDConstants.ACTION_NONE;
// The native context is invalid after the drop is done.
// Clear the reference to prohibit access.
nativeDragContext = 0;
}
}
protected abstract void doDropDone(boolean success,
int dropAction, boolean isLocal);
protected synchronized long getNativeDragContext() {
return nativeDragContext;
}
protected void eventPosted(SunDropTargetEvent e) {}
protected void eventProcessed(SunDropTargetEvent e, int returnValue,
boolean dispatcherDone) {}
protected static class EventDispatcher {
private final SunDropTargetContextPeer peer;
// context fields
private final int dropAction;
private final int actions;
private final long[] formats;
private long nativeCtxt;
private final boolean dispatchType;
private boolean dispatcherDone = false;
// dispatcher state fields
private int returnValue = 0;
// set of events to be dispatched by this dispatcher
private final HashSet eventSet = new HashSet(3);
static final ToolkitThreadBlockedHandler handler =
DataTransferer.getInstance().getToolkitThreadBlockedHandler();
EventDispatcher(SunDropTargetContextPeer peer,
int dropAction,
int actions,
long[] formats,
long nativeCtxt,
boolean dispatchType) {
this.peer = peer;
this.nativeCtxt = nativeCtxt;
this.dropAction = dropAction;
this.actions = actions;
this.formats =
(null == formats) ? null : Arrays.copyOf(formats, formats.length);
this.dispatchType = dispatchType;
}
void dispatchEvent(SunDropTargetEvent e) {
int id = e.getID();
switch (id) {
case SunDropTargetEvent.MOUSE_ENTERED:
dispatchEnterEvent(e);
break;
case SunDropTargetEvent.MOUSE_DRAGGED:
dispatchMotionEvent(e);
break;
case SunDropTargetEvent.MOUSE_EXITED:
dispatchExitEvent(e);
break;
case SunDropTargetEvent.MOUSE_DROPPED:
dispatchDropEvent(e);
break;
default:
throw new InvalidDnDOperationException();
}
}
private void dispatchEnterEvent(SunDropTargetEvent e) {
synchronized (peer) {
// store the drop action here to track operation changes
peer.previousDA = dropAction;
// setup peer context
peer.nativeDragContext = nativeCtxt;
peer.currentT = formats;
peer.currentSA = actions;
peer.currentDA = dropAction;
// To allow data retrieval.
peer.dropStatus = STATUS_ACCEPT;
peer.dropComplete = false;
try {
peer.processEnterMessage(e);
} finally {
peer.dropStatus = STATUS_NONE;
}
setReturnValue(peer.currentDA);
}
}
private void dispatchMotionEvent(SunDropTargetEvent e) {
synchronized (peer) {
boolean operationChanged = peer.previousDA != dropAction;
peer.previousDA = dropAction;
// setup peer context
peer.nativeDragContext = nativeCtxt;
peer.currentT = formats;
peer.currentSA = actions;
peer.currentDA = dropAction;
// To allow data retrieval.
peer.dropStatus = STATUS_ACCEPT;
peer.dropComplete = false;
try {
peer.processMotionMessage(e, operationChanged);
} finally {
peer.dropStatus = STATUS_NONE;
}
setReturnValue(peer.currentDA);
}
}
private void dispatchExitEvent(SunDropTargetEvent e) {
synchronized (peer) {
// setup peer context
peer.nativeDragContext = nativeCtxt;
peer.processExitMessage(e);
}
}
private void dispatchDropEvent(SunDropTargetEvent e) {
synchronized (peer) {
// setup peer context
peer.nativeDragContext = nativeCtxt;
peer.currentT = formats;
peer.currentSA = actions;
peer.currentDA = dropAction;
peer.processDropMessage(e);
}
}
void setReturnValue(int ret) {
returnValue = ret;
}
int getReturnValue() {
return returnValue;
}
boolean isDone() {
return eventSet.isEmpty();
}
void registerEvent(SunDropTargetEvent e) {
handler.lock();
if (!eventSet.add(e) && dndLog.isLoggable(PlatformLogger.Level.FINE)) {
dndLog.fine("Event is already registered: " + e);
}
handler.unlock();
}
void unregisterEvent(SunDropTargetEvent e) {
handler.lock();
try {
if (!eventSet.remove(e)) {
// This event has already been unregistered.
return;
}
if (eventSet.isEmpty()) {
if (!dispatcherDone && dispatchType == DISPATCH_SYNC) {
handler.exit();
}
dispatcherDone = true;
}
} finally {
handler.unlock();
}
try {
peer.eventProcessed(e, returnValue, dispatcherDone);
} finally {
/*
* Clear the reference to the native context if all copies of
* the original event are processed.
*/
if (dispatcherDone) {
nativeCtxt = 0;
// Fix for 6342381
peer.nativeDragContext = 0;
}
}
}
public void unregisterAllEvents() {
Object[] events = null;
handler.lock();
try {
events = eventSet.toArray();
} finally {
handler.unlock();
}
if (events != null) {
for (int i = 0; i < events.length; i++) {
unregisterEvent((SunDropTargetEvent)events[i]);
}
}
}
}
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright (c) 2000, 2004, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.dnd;
import java.awt.Component;
import java.awt.dnd.InvalidDnDOperationException;
import java.awt.event.MouseEvent;
public class SunDropTargetEvent extends MouseEvent {
public static final int MOUSE_DROPPED = MouseEvent.MOUSE_RELEASED;
private final SunDropTargetContextPeer.EventDispatcher dispatcher;
public SunDropTargetEvent(Component source, int id, int x, int y,
SunDropTargetContextPeer.EventDispatcher d) {
super(source, id, System.currentTimeMillis(), 0, x, y, 0, 0, 0,
false, MouseEvent.NOBUTTON);
dispatcher = d;
dispatcher.registerEvent(this);
}
public void dispatch() {
try {
dispatcher.dispatchEvent(this);
} finally {
dispatcher.unregisterEvent(this);
}
}
public void consume() {
boolean was_consumed = isConsumed();
super.consume();
if (!was_consumed && isConsumed()) {
dispatcher.unregisterEvent(this);
}
}
public SunDropTargetContextPeer.EventDispatcher getDispatcher() {
return dispatcher;
}
public String paramString() {
String typeStr = null;
switch (id) {
case MOUSE_DROPPED:
typeStr = "MOUSE_DROPPED"; break;
default:
return super.paramString();
}
return typeStr + ",(" + getX() + "," + getY() + ")";
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2005, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.event;
import java.awt.Component;
import java.awt.Rectangle;
import java.awt.event.PaintEvent;
/**
* PaintEvents that are effectively ignored. This class is used only for
* tagging. If a heavy weight peer is asked to handle an event of this
* class it'll ignore it. This class is used by Swing.
* Look at <code>javax.swing.SwingPaintEventDispatcher</code> for more.
*
*/
public class IgnorePaintEvent extends PaintEvent {
public IgnorePaintEvent(Component source, int id, Rectangle updateRect) {
super(source, id, updateRect);
}
}

View File

@@ -0,0 +1,561 @@
/*
* Copyright (c) 1998, 2003, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.geom;
import java.util.Vector;
import java.util.Enumeration;
import java.util.Comparator;
import java.util.Arrays;
public abstract class AreaOp {
public static abstract class CAGOp extends AreaOp {
boolean inLeft;
boolean inRight;
boolean inResult;
public void newRow() {
inLeft = false;
inRight = false;
inResult = false;
}
public int classify(Edge e) {
if (e.getCurveTag() == CTAG_LEFT) {
inLeft = !inLeft;
} else {
inRight = !inRight;
}
boolean newClass = newClassification(inLeft, inRight);
if (inResult == newClass) {
return ETAG_IGNORE;
}
inResult = newClass;
return (newClass ? ETAG_ENTER : ETAG_EXIT);
}
public int getState() {
return (inResult ? RSTAG_INSIDE : RSTAG_OUTSIDE);
}
public abstract boolean newClassification(boolean inLeft,
boolean inRight);
}
public static class AddOp extends CAGOp {
public boolean newClassification(boolean inLeft, boolean inRight) {
return (inLeft || inRight);
}
}
public static class SubOp extends CAGOp {
public boolean newClassification(boolean inLeft, boolean inRight) {
return (inLeft && !inRight);
}
}
public static class IntOp extends CAGOp {
public boolean newClassification(boolean inLeft, boolean inRight) {
return (inLeft && inRight);
}
}
public static class XorOp extends CAGOp {
public boolean newClassification(boolean inLeft, boolean inRight) {
return (inLeft != inRight);
}
}
public static class NZWindOp extends AreaOp {
private int count;
public void newRow() {
count = 0;
}
public int classify(Edge e) {
// Note: the right curves should be an empty set with this op...
// assert(e.getCurveTag() == CTAG_LEFT);
int newCount = count;
int type = (newCount == 0 ? ETAG_ENTER : ETAG_IGNORE);
newCount += e.getCurve().getDirection();
count = newCount;
return (newCount == 0 ? ETAG_EXIT : type);
}
public int getState() {
return ((count == 0) ? RSTAG_OUTSIDE : RSTAG_INSIDE);
}
}
public static class EOWindOp extends AreaOp {
private boolean inside;
public void newRow() {
inside = false;
}
public int classify(Edge e) {
// Note: the right curves should be an empty set with this op...
// assert(e.getCurveTag() == CTAG_LEFT);
boolean newInside = !inside;
inside = newInside;
return (newInside ? ETAG_ENTER : ETAG_EXIT);
}
public int getState() {
return (inside ? RSTAG_INSIDE : RSTAG_OUTSIDE);
}
}
private AreaOp() {
}
/* Constants to tag the left and right curves in the edge list */
public static final int CTAG_LEFT = 0;
public static final int CTAG_RIGHT = 1;
/* Constants to classify edges */
public static final int ETAG_IGNORE = 0;
public static final int ETAG_ENTER = 1;
public static final int ETAG_EXIT = -1;
/* Constants used to classify result state */
public static final int RSTAG_INSIDE = 1;
public static final int RSTAG_OUTSIDE = -1;
public abstract void newRow();
public abstract int classify(Edge e);
public abstract int getState();
public Vector calculate(Vector left, Vector right) {
Vector edges = new Vector();
addEdges(edges, left, AreaOp.CTAG_LEFT);
addEdges(edges, right, AreaOp.CTAG_RIGHT);
edges = pruneEdges(edges);
if (false) {
System.out.println("result: ");
int numcurves = edges.size();
Curve[] curvelist = (Curve[]) edges.toArray(new Curve[numcurves]);
for (int i = 0; i < numcurves; i++) {
System.out.println("curvelist["+i+"] = "+curvelist[i]);
}
}
return edges;
}
private static void addEdges(Vector edges, Vector curves, int curvetag) {
Enumeration enum_ = curves.elements();
while (enum_.hasMoreElements()) {
Curve c = (Curve) enum_.nextElement();
if (c.getOrder() > 0) {
edges.add(new Edge(c, curvetag));
}
}
}
private static Comparator YXTopComparator = new Comparator() {
public int compare(Object o1, Object o2) {
Curve c1 = ((Edge) o1).getCurve();
Curve c2 = ((Edge) o2).getCurve();
double v1, v2;
if ((v1 = c1.getYTop()) == (v2 = c2.getYTop())) {
if ((v1 = c1.getXTop()) == (v2 = c2.getXTop())) {
return 0;
}
}
if (v1 < v2) {
return -1;
}
return 1;
}
};
private Vector pruneEdges(Vector edges) {
int numedges = edges.size();
if (numedges < 2) {
return edges;
}
Edge[] edgelist = (Edge[]) edges.toArray(new Edge[numedges]);
Arrays.sort(edgelist, YXTopComparator);
if (false) {
System.out.println("pruning: ");
for (int i = 0; i < numedges; i++) {
System.out.println("edgelist["+i+"] = "+edgelist[i]);
}
}
Edge e;
int left = 0;
int right = 0;
int cur = 0;
int next = 0;
double yrange[] = new double[2];
Vector subcurves = new Vector();
Vector chains = new Vector();
Vector links = new Vector();
// Active edges are between left (inclusive) and right (exclusive)
while (left < numedges) {
double y = yrange[0];
// Prune active edges that fall off the top of the active y range
for (cur = next = right - 1; cur >= left; cur--) {
e = edgelist[cur];
if (e.getCurve().getYBot() > y) {
if (next > cur) {
edgelist[next] = e;
}
next--;
}
}
left = next + 1;
// Grab a new "top of Y range" if the active edges are empty
if (left >= right) {
if (right >= numedges) {
break;
}
y = edgelist[right].getCurve().getYTop();
if (y > yrange[0]) {
finalizeSubCurves(subcurves, chains);
}
yrange[0] = y;
}
// Incorporate new active edges that enter the active y range
while (right < numedges) {
e = edgelist[right];
if (e.getCurve().getYTop() > y) {
break;
}
right++;
}
// Sort the current active edges by their X values and
// determine the maximum valid Y range where the X ordering
// is correct
yrange[1] = edgelist[left].getCurve().getYBot();
if (right < numedges) {
y = edgelist[right].getCurve().getYTop();
if (yrange[1] > y) {
yrange[1] = y;
}
}
if (false) {
System.out.println("current line: y = ["+
yrange[0]+", "+yrange[1]+"]");
for (cur = left; cur < right; cur++) {
System.out.println(" "+edgelist[cur]);
}
}
// Note: We could start at left+1, but we need to make
// sure that edgelist[left] has its equivalence set to 0.
int nexteq = 1;
for (cur = left; cur < right; cur++) {
e = edgelist[cur];
e.setEquivalence(0);
for (next = cur; next > left; next--) {
Edge prevedge = edgelist[next-1];
int ordering = e.compareTo(prevedge, yrange);
if (yrange[1] <= yrange[0]) {
throw new InternalError("backstepping to "+yrange[1]+
" from "+yrange[0]);
}
if (ordering >= 0) {
if (ordering == 0) {
// If the curves are equal, mark them to be
// deleted later if they cancel each other
// out so that we avoid having extraneous
// curve segments.
int eq = prevedge.getEquivalence();
if (eq == 0) {
eq = nexteq++;
prevedge.setEquivalence(eq);
}
e.setEquivalence(eq);
}
break;
}
edgelist[next] = prevedge;
}
edgelist[next] = e;
}
if (false) {
System.out.println("current sorted line: y = ["+
yrange[0]+", "+yrange[1]+"]");
for (cur = left; cur < right; cur++) {
System.out.println(" "+edgelist[cur]);
}
}
// Now prune the active edge list.
// For each edge in the list, determine its classification
// (entering shape, exiting shape, ignore - no change) and
// record the current Y range and its classification in the
// Edge object for use later in constructing the new outline.
newRow();
double ystart = yrange[0];
double yend = yrange[1];
for (cur = left; cur < right; cur++) {
e = edgelist[cur];
int etag;
int eq = e.getEquivalence();
if (eq != 0) {
// Find one of the segments in the "equal" range
// with the right transition state and prefer an
// edge that was either active up until ystart
// or the edge that extends the furthest downward
// (i.e. has the most potential for continuation)
int origstate = getState();
etag = (origstate == AreaOp.RSTAG_INSIDE
? AreaOp.ETAG_EXIT
: AreaOp.ETAG_ENTER);
Edge activematch = null;
Edge longestmatch = e;
double furthesty = yend;
do {
// Note: classify() must be called
// on every edge we consume here.
classify(e);
if (activematch == null &&
e.isActiveFor(ystart, etag))
{
activematch = e;
}
y = e.getCurve().getYBot();
if (y > furthesty) {
longestmatch = e;
furthesty = y;
}
} while (++cur < right &&
(e = edgelist[cur]).getEquivalence() == eq);
--cur;
if (getState() == origstate) {
etag = AreaOp.ETAG_IGNORE;
} else {
e = (activematch != null ? activematch : longestmatch);
}
} else {
etag = classify(e);
}
if (etag != AreaOp.ETAG_IGNORE) {
e.record(yend, etag);
links.add(new CurveLink(e.getCurve(), ystart, yend, etag));
}
}
// assert(getState() == AreaOp.RSTAG_OUTSIDE);
if (getState() != AreaOp.RSTAG_OUTSIDE) {
System.out.println("Still inside at end of active edge list!");
System.out.println("num curves = "+(right-left));
System.out.println("num links = "+links.size());
System.out.println("y top = "+yrange[0]);
if (right < numedges) {
System.out.println("y top of next curve = "+
edgelist[right].getCurve().getYTop());
} else {
System.out.println("no more curves");
}
for (cur = left; cur < right; cur++) {
e = edgelist[cur];
System.out.println(e);
int eq = e.getEquivalence();
if (eq != 0) {
System.out.println(" was equal to "+eq+"...");
}
}
}
if (false) {
System.out.println("new links:");
for (int i = 0; i < links.size(); i++) {
CurveLink link = (CurveLink) links.elementAt(i);
System.out.println(" "+link.getSubCurve());
}
}
resolveLinks(subcurves, chains, links);
links.clear();
// Finally capture the bottom of the valid Y range as the top
// of the next Y range.
yrange[0] = yend;
}
finalizeSubCurves(subcurves, chains);
Vector ret = new Vector();
Enumeration enum_ = subcurves.elements();
while (enum_.hasMoreElements()) {
CurveLink link = (CurveLink) enum_.nextElement();
ret.add(link.getMoveto());
CurveLink nextlink = link;
while ((nextlink = nextlink.getNext()) != null) {
if (!link.absorb(nextlink)) {
ret.add(link.getSubCurve());
link = nextlink;
}
}
ret.add(link.getSubCurve());
}
return ret;
}
public static void finalizeSubCurves(Vector subcurves, Vector chains) {
int numchains = chains.size();
if (numchains == 0) {
return;
}
if ((numchains & 1) != 0) {
throw new InternalError("Odd number of chains!");
}
ChainEnd[] endlist = new ChainEnd[numchains];
chains.toArray(endlist);
for (int i = 1; i < numchains; i += 2) {
ChainEnd open = endlist[i - 1];
ChainEnd close = endlist[i];
CurveLink subcurve = open.linkTo(close);
if (subcurve != null) {
subcurves.add(subcurve);
}
}
chains.clear();
}
private static CurveLink[] EmptyLinkList = new CurveLink[2];
private static ChainEnd[] EmptyChainList = new ChainEnd[2];
public static void resolveLinks(Vector subcurves,
Vector chains,
Vector links)
{
int numlinks = links.size();
CurveLink[] linklist;
if (numlinks == 0) {
linklist = EmptyLinkList;
} else {
if ((numlinks & 1) != 0) {
throw new InternalError("Odd number of new curves!");
}
linklist = new CurveLink[numlinks+2];
links.toArray(linklist);
}
int numchains = chains.size();
ChainEnd[] endlist;
if (numchains == 0) {
endlist = EmptyChainList;
} else {
if ((numchains & 1) != 0) {
throw new InternalError("Odd number of chains!");
}
endlist = new ChainEnd[numchains+2];
chains.toArray(endlist);
}
int curchain = 0;
int curlink = 0;
chains.clear();
ChainEnd chain = endlist[0];
ChainEnd nextchain = endlist[1];
CurveLink link = linklist[0];
CurveLink nextlink = linklist[1];
while (chain != null || link != null) {
/*
* Strategy 1:
* Connect chains or links if they are the only things left...
*/
boolean connectchains = (link == null);
boolean connectlinks = (chain == null);
if (!connectchains && !connectlinks) {
// assert(link != null && chain != null);
/*
* Strategy 2:
* Connect chains or links if they close off an open area...
*/
connectchains = ((curchain & 1) == 0 &&
chain.getX() == nextchain.getX());
connectlinks = ((curlink & 1) == 0 &&
link.getX() == nextlink.getX());
if (!connectchains && !connectlinks) {
/*
* Strategy 3:
* Connect chains or links if their successor is
* between them and their potential connectee...
*/
double cx = chain.getX();
double lx = link.getX();
connectchains =
(nextchain != null && cx < lx &&
obstructs(nextchain.getX(), lx, curchain));
connectlinks =
(nextlink != null && lx < cx &&
obstructs(nextlink.getX(), cx, curlink));
}
}
if (connectchains) {
CurveLink subcurve = chain.linkTo(nextchain);
if (subcurve != null) {
subcurves.add(subcurve);
}
curchain += 2;
chain = endlist[curchain];
nextchain = endlist[curchain+1];
}
if (connectlinks) {
ChainEnd openend = new ChainEnd(link, null);
ChainEnd closeend = new ChainEnd(nextlink, openend);
openend.setOtherEnd(closeend);
chains.add(openend);
chains.add(closeend);
curlink += 2;
link = linklist[curlink];
nextlink = linklist[curlink+1];
}
if (!connectchains && !connectlinks) {
// assert(link != null);
// assert(chain != null);
// assert(chain.getEtag() == link.getEtag());
chain.addLink(link);
chains.add(chain);
curchain++;
chain = nextchain;
nextchain = endlist[curchain+1];
curlink++;
link = nextlink;
nextlink = linklist[curlink+1];
}
}
if ((chains.size() & 1) != 0) {
System.out.println("Odd number of chains!");
}
}
/*
* Does the position of the next edge at v1 "obstruct" the
* connectivity between current edge and the potential
* partner edge which is positioned at v2?
*
* Phase tells us whether we are testing for a transition
* into or out of the interior part of the resulting area.
*
* Require 4-connected continuity if this edge and the partner
* edge are both "entering into" type edges
* Allow 8-connected continuity for "exiting from" type edges
*/
public static boolean obstructs(double v1, double v2, int phase) {
return (((phase & 1) == 0) ? (v1 <= v2) : (v1 < v2));
}
}

View File

@@ -0,0 +1,117 @@
/*
* Copyright (c) 1998, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.geom;
final class ChainEnd {
CurveLink head;
CurveLink tail;
ChainEnd partner;
int etag;
public ChainEnd(CurveLink first, ChainEnd partner) {
this.head = first;
this.tail = first;
this.partner = partner;
this.etag = first.getEdgeTag();
}
public CurveLink getChain() {
return head;
}
public void setOtherEnd(ChainEnd partner) {
this.partner = partner;
}
public ChainEnd getPartner() {
return partner;
}
/*
* Returns head of a complete chain to be added to subcurves
* or null if the links did not complete such a chain.
*/
public CurveLink linkTo(ChainEnd that) {
if (etag == AreaOp.ETAG_IGNORE ||
that.etag == AreaOp.ETAG_IGNORE)
{
throw new InternalError("ChainEnd linked more than once!");
}
if (etag == that.etag) {
throw new InternalError("Linking chains of the same type!");
}
ChainEnd enter, exit;
// assert(partner.etag != that.partner.etag);
if (etag == AreaOp.ETAG_ENTER) {
enter = this;
exit = that;
} else {
enter = that;
exit = this;
}
// Now make sure these ChainEnds are not linked to any others...
etag = AreaOp.ETAG_IGNORE;
that.etag = AreaOp.ETAG_IGNORE;
// Now link everything up...
enter.tail.setNext(exit.head);
enter.tail = exit.tail;
if (partner == that) {
// Curve has closed on itself...
return enter.head;
}
// Link this chain into one end of the chain formed by the partners
ChainEnd otherenter = exit.partner;
ChainEnd otherexit = enter.partner;
otherenter.partner = otherexit;
otherexit.partner = otherenter;
if (enter.head.getYTop() < otherenter.head.getYTop()) {
enter.tail.setNext(otherenter.head);
otherenter.head = enter.head;
} else {
otherexit.tail.setNext(enter.head);
otherexit.tail = enter.tail;
}
return null;
}
public void addLink(CurveLink newlink) {
if (etag == AreaOp.ETAG_ENTER) {
tail.setNext(newlink);
tail = newlink;
} else {
newlink.setNext(head);
head = newlink;
}
}
public double getX() {
if (etag == AreaOp.ETAG_ENTER) {
return tail.getXBot();
} else {
return head.getXBot();
}
}
}

View File

@@ -0,0 +1,522 @@
/*
* Copyright (c) 1998, 2003, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.geom;
import java.awt.geom.PathIterator;
import java.util.Vector;
import java.util.Enumeration;
public abstract class Crossings {
public static final boolean debug = false;
int limit = 0;
double yranges[] = new double[10];
double xlo, ylo, xhi, yhi;
public Crossings(double xlo, double ylo, double xhi, double yhi) {
this.xlo = xlo;
this.ylo = ylo;
this.xhi = xhi;
this.yhi = yhi;
}
public final double getXLo() {
return xlo;
}
public final double getYLo() {
return ylo;
}
public final double getXHi() {
return xhi;
}
public final double getYHi() {
return yhi;
}
public abstract void record(double ystart, double yend, int direction);
public void print() {
System.out.println("Crossings [");
System.out.println(" bounds = ["+ylo+", "+yhi+"]");
for (int i = 0; i < limit; i += 2) {
System.out.println(" ["+yranges[i]+", "+yranges[i+1]+"]");
}
System.out.println("]");
}
public final boolean isEmpty() {
return (limit == 0);
}
public abstract boolean covers(double ystart, double yend);
public static Crossings findCrossings(Vector curves,
double xlo, double ylo,
double xhi, double yhi)
{
Crossings cross = new EvenOdd(xlo, ylo, xhi, yhi);
Enumeration enum_ = curves.elements();
while (enum_.hasMoreElements()) {
Curve c = (Curve) enum_.nextElement();
if (c.accumulateCrossings(cross)) {
return null;
}
}
if (debug) {
cross.print();
}
return cross;
}
public static Crossings findCrossings(PathIterator pi,
double xlo, double ylo,
double xhi, double yhi)
{
Crossings cross;
if (pi.getWindingRule() == pi.WIND_EVEN_ODD) {
cross = new EvenOdd(xlo, ylo, xhi, yhi);
} else {
cross = new NonZero(xlo, ylo, xhi, yhi);
}
// coords array is big enough for holding:
// coordinates returned from currentSegment (6)
// OR
// two subdivided quadratic curves (2+4+4=10)
// AND
// 0-1 horizontal splitting parameters
// OR
// 2 parametric equation derivative coefficients
// OR
// three subdivided cubic curves (2+6+6+6=20)
// AND
// 0-2 horizontal splitting parameters
// OR
// 3 parametric equation derivative coefficients
double coords[] = new double[23];
double movx = 0;
double movy = 0;
double curx = 0;
double cury = 0;
double newx, newy;
while (!pi.isDone()) {
int type = pi.currentSegment(coords);
switch (type) {
case PathIterator.SEG_MOVETO:
if (movy != cury &&
cross.accumulateLine(curx, cury, movx, movy))
{
return null;
}
movx = curx = coords[0];
movy = cury = coords[1];
break;
case PathIterator.SEG_LINETO:
newx = coords[0];
newy = coords[1];
if (cross.accumulateLine(curx, cury, newx, newy)) {
return null;
}
curx = newx;
cury = newy;
break;
case PathIterator.SEG_QUADTO:
newx = coords[2];
newy = coords[3];
if (cross.accumulateQuad(curx, cury, coords)) {
return null;
}
curx = newx;
cury = newy;
break;
case PathIterator.SEG_CUBICTO:
newx = coords[4];
newy = coords[5];
if (cross.accumulateCubic(curx, cury, coords)) {
return null;
}
curx = newx;
cury = newy;
break;
case PathIterator.SEG_CLOSE:
if (movy != cury &&
cross.accumulateLine(curx, cury, movx, movy))
{
return null;
}
curx = movx;
cury = movy;
break;
}
pi.next();
}
if (movy != cury) {
if (cross.accumulateLine(curx, cury, movx, movy)) {
return null;
}
}
if (debug) {
cross.print();
}
return cross;
}
public boolean accumulateLine(double x0, double y0,
double x1, double y1)
{
if (y0 <= y1) {
return accumulateLine(x0, y0, x1, y1, 1);
} else {
return accumulateLine(x1, y1, x0, y0, -1);
}
}
public boolean accumulateLine(double x0, double y0,
double x1, double y1,
int direction)
{
if (yhi <= y0 || ylo >= y1) {
return false;
}
if (x0 >= xhi && x1 >= xhi) {
return false;
}
if (y0 == y1) {
return (x0 >= xlo || x1 >= xlo);
}
double xstart, ystart, xend, yend;
double dx = (x1 - x0);
double dy = (y1 - y0);
if (y0 < ylo) {
xstart = x0 + (ylo - y0) * dx / dy;
ystart = ylo;
} else {
xstart = x0;
ystart = y0;
}
if (yhi < y1) {
xend = x0 + (yhi - y0) * dx / dy;
yend = yhi;
} else {
xend = x1;
yend = y1;
}
if (xstart >= xhi && xend >= xhi) {
return false;
}
if (xstart > xlo || xend > xlo) {
return true;
}
record(ystart, yend, direction);
return false;
}
private Vector tmp = new Vector();
public boolean accumulateQuad(double x0, double y0, double coords[]) {
if (y0 < ylo && coords[1] < ylo && coords[3] < ylo) {
return false;
}
if (y0 > yhi && coords[1] > yhi && coords[3] > yhi) {
return false;
}
if (x0 > xhi && coords[0] > xhi && coords[2] > xhi) {
return false;
}
if (x0 < xlo && coords[0] < xlo && coords[2] < xlo) {
if (y0 < coords[3]) {
record(Math.max(y0, ylo), Math.min(coords[3], yhi), 1);
} else if (y0 > coords[3]) {
record(Math.max(coords[3], ylo), Math.min(y0, yhi), -1);
}
return false;
}
Curve.insertQuad(tmp, x0, y0, coords);
Enumeration enum_ = tmp.elements();
while (enum_.hasMoreElements()) {
Curve c = (Curve) enum_.nextElement();
if (c.accumulateCrossings(this)) {
return true;
}
}
tmp.clear();
return false;
}
public boolean accumulateCubic(double x0, double y0, double coords[]) {
if (y0 < ylo && coords[1] < ylo &&
coords[3] < ylo && coords[5] < ylo)
{
return false;
}
if (y0 > yhi && coords[1] > yhi &&
coords[3] > yhi && coords[5] > yhi)
{
return false;
}
if (x0 > xhi && coords[0] > xhi &&
coords[2] > xhi && coords[4] > xhi)
{
return false;
}
if (x0 < xlo && coords[0] < xlo &&
coords[2] < xlo && coords[4] < xlo)
{
if (y0 <= coords[5]) {
record(Math.max(y0, ylo), Math.min(coords[5], yhi), 1);
} else {
record(Math.max(coords[5], ylo), Math.min(y0, yhi), -1);
}
return false;
}
Curve.insertCubic(tmp, x0, y0, coords);
Enumeration enum_ = tmp.elements();
while (enum_.hasMoreElements()) {
Curve c = (Curve) enum_.nextElement();
if (c.accumulateCrossings(this)) {
return true;
}
}
tmp.clear();
return false;
}
public final static class EvenOdd extends Crossings {
public EvenOdd(double xlo, double ylo, double xhi, double yhi) {
super(xlo, ylo, xhi, yhi);
}
public final boolean covers(double ystart, double yend) {
return (limit == 2 && yranges[0] <= ystart && yranges[1] >= yend);
}
public void record(double ystart, double yend, int direction) {
if (ystart >= yend) {
return;
}
int from = 0;
// Quickly jump over all pairs that are completely "above"
while (from < limit && ystart > yranges[from+1]) {
from += 2;
}
int to = from;
while (from < limit) {
double yrlo = yranges[from++];
double yrhi = yranges[from++];
if (yend < yrlo) {
// Quickly handle insertion of the new range
yranges[to++] = ystart;
yranges[to++] = yend;
ystart = yrlo;
yend = yrhi;
continue;
}
// The ranges overlap - sort, collapse, insert, iterate
double yll, ylh, yhl, yhh;
if (ystart < yrlo) {
yll = ystart;
ylh = yrlo;
} else {
yll = yrlo;
ylh = ystart;
}
if (yend < yrhi) {
yhl = yend;
yhh = yrhi;
} else {
yhl = yrhi;
yhh = yend;
}
if (ylh == yhl) {
ystart = yll;
yend = yhh;
} else {
if (ylh > yhl) {
ystart = yhl;
yhl = ylh;
ylh = ystart;
}
if (yll != ylh) {
yranges[to++] = yll;
yranges[to++] = ylh;
}
ystart = yhl;
yend = yhh;
}
if (ystart >= yend) {
break;
}
}
if (to < from && from < limit) {
System.arraycopy(yranges, from, yranges, to, limit-from);
}
to += (limit-from);
if (ystart < yend) {
if (to >= yranges.length) {
double newranges[] = new double[to+10];
System.arraycopy(yranges, 0, newranges, 0, to);
yranges = newranges;
}
yranges[to++] = ystart;
yranges[to++] = yend;
}
limit = to;
}
}
public final static class NonZero extends Crossings {
private int crosscounts[];
public NonZero(double xlo, double ylo, double xhi, double yhi) {
super(xlo, ylo, xhi, yhi);
crosscounts = new int[yranges.length / 2];
}
public final boolean covers(double ystart, double yend) {
int i = 0;
while (i < limit) {
double ylo = yranges[i++];
double yhi = yranges[i++];
if (ystart >= yhi) {
continue;
}
if (ystart < ylo) {
return false;
}
if (yend <= yhi) {
return true;
}
ystart = yhi;
}
return (ystart >= yend);
}
public void remove(int cur) {
limit -= 2;
int rem = limit - cur;
if (rem > 0) {
System.arraycopy(yranges, cur+2, yranges, cur, rem);
System.arraycopy(crosscounts, cur/2+1,
crosscounts, cur/2,
rem/2);
}
}
public void insert(int cur, double lo, double hi, int dir) {
int rem = limit - cur;
double oldranges[] = yranges;
int oldcounts[] = crosscounts;
if (limit >= yranges.length) {
yranges = new double[limit+10];
System.arraycopy(oldranges, 0, yranges, 0, cur);
crosscounts = new int[(limit+10)/2];
System.arraycopy(oldcounts, 0, crosscounts, 0, cur/2);
}
if (rem > 0) {
System.arraycopy(oldranges, cur, yranges, cur+2, rem);
System.arraycopy(oldcounts, cur/2,
crosscounts, cur/2+1,
rem/2);
}
yranges[cur+0] = lo;
yranges[cur+1] = hi;
crosscounts[cur/2] = dir;
limit += 2;
}
public void record(double ystart, double yend, int direction) {
if (ystart >= yend) {
return;
}
int cur = 0;
// Quickly jump over all pairs that are completely "above"
while (cur < limit && ystart > yranges[cur+1]) {
cur += 2;
}
if (cur < limit) {
int rdir = crosscounts[cur/2];
double yrlo = yranges[cur+0];
double yrhi = yranges[cur+1];
if (yrhi == ystart && rdir == direction) {
// Remove the range from the list and collapse it
// into the range being inserted. Note that the
// new combined range may overlap the following range
// so we must not simply combine the ranges in place
// unless we are at the last range.
if (cur+2 == limit) {
yranges[cur+1] = yend;
return;
}
remove(cur);
ystart = yrlo;
rdir = crosscounts[cur/2];
yrlo = yranges[cur+0];
yrhi = yranges[cur+1];
}
if (yend < yrlo) {
// Just insert the new range at the current location
insert(cur, ystart, yend, direction);
return;
}
if (yend == yrlo && rdir == direction) {
// Just prepend the new range to the current one
yranges[cur] = ystart;
return;
}
// The ranges must overlap - (yend > yrlo && yrhi > ystart)
if (ystart < yrlo) {
insert(cur, ystart, yrlo, direction);
cur += 2;
ystart = yrlo;
} else if (yrlo < ystart) {
insert(cur, yrlo, ystart, rdir);
cur += 2;
yrlo = ystart;
}
// assert(yrlo == ystart);
int newdir = rdir + direction;
double newend = Math.min(yend, yrhi);
if (newdir == 0) {
remove(cur);
} else {
crosscounts[cur/2] = newdir;
yranges[cur++] = ystart;
yranges[cur++] = newend;
}
ystart = yrlo = newend;
if (yrlo < yrhi) {
insert(cur, yrlo, yrhi, rdir);
}
}
if (ystart < yend) {
insert(cur, ystart, yend, direction);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,114 @@
/*
* Copyright (c) 1998, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.geom;
final class CurveLink {
Curve curve;
double ytop;
double ybot;
int etag;
CurveLink next;
public CurveLink(Curve curve, double ystart, double yend, int etag) {
this.curve = curve;
this.ytop = ystart;
this.ybot = yend;
this.etag = etag;
if (ytop < curve.getYTop() || ybot > curve.getYBot()) {
throw new InternalError("bad curvelink ["+ytop+"=>"+ybot+"] for "+curve);
}
}
public boolean absorb(CurveLink link) {
return absorb(link.curve, link.ytop, link.ybot, link.etag);
}
public boolean absorb(Curve curve, double ystart, double yend, int etag) {
if (this.curve != curve || this.etag != etag ||
ybot < ystart || ytop > yend)
{
return false;
}
if (ystart < curve.getYTop() || yend > curve.getYBot()) {
throw new InternalError("bad curvelink ["+ystart+"=>"+yend+"] for "+curve);
}
this.ytop = Math.min(ytop, ystart);
this.ybot = Math.max(ybot, yend);
return true;
}
public boolean isEmpty() {
return (ytop == ybot);
}
public Curve getCurve() {
return curve;
}
public Curve getSubCurve() {
if (ytop == curve.getYTop() && ybot == curve.getYBot()) {
return curve.getWithDirection(etag);
}
return curve.getSubCurve(ytop, ybot, etag);
}
public Curve getMoveto() {
return new Order0(getXTop(), getYTop());
}
public double getXTop() {
return curve.XforY(ytop);
}
public double getYTop() {
return ytop;
}
public double getXBot() {
return curve.XforY(ybot);
}
public double getYBot() {
return ybot;
}
public double getX() {
return curve.XforY(ytop);
}
public int getEdgeTag() {
return etag;
}
public void setNext(CurveLink link) {
this.next = link;
}
public CurveLink getNext() {
return next;
}
}

View File

@@ -0,0 +1,125 @@
/*
* Copyright (c) 1998, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.geom;
final class Edge {
static final int INIT_PARTS = 4;
static final int GROW_PARTS = 10;
Curve curve;
int ctag;
int etag;
double activey;
int equivalence;
public Edge(Curve c, int ctag) {
this(c, ctag, AreaOp.ETAG_IGNORE);
}
public Edge(Curve c, int ctag, int etag) {
this.curve = c;
this.ctag = ctag;
this.etag = etag;
}
public Curve getCurve() {
return curve;
}
public int getCurveTag() {
return ctag;
}
public int getEdgeTag() {
return etag;
}
public void setEdgeTag(int etag) {
this.etag = etag;
}
public int getEquivalence() {
return equivalence;
}
public void setEquivalence(int eq) {
equivalence = eq;
}
private Edge lastEdge;
private int lastResult;
private double lastLimit;
public int compareTo(Edge other, double yrange[]) {
if (other == lastEdge && yrange[0] < lastLimit) {
if (yrange[1] > lastLimit) {
yrange[1] = lastLimit;
}
return lastResult;
}
if (this == other.lastEdge && yrange[0] < other.lastLimit) {
if (yrange[1] > other.lastLimit) {
yrange[1] = other.lastLimit;
}
return 0-other.lastResult;
}
//long start = System.currentTimeMillis();
int ret = curve.compareTo(other.curve, yrange);
//long end = System.currentTimeMillis();
/*
System.out.println("compare: "+
((System.identityHashCode(this) <
System.identityHashCode(other))
? this+" to "+other
: other+" to "+this)+
" == "+ret+" at "+yrange[1]+
" in "+(end-start)+"ms");
*/
lastEdge = other;
lastLimit = yrange[1];
lastResult = ret;
return ret;
}
public void record(double yend, int etag) {
this.activey = yend;
this.etag = etag;
}
public boolean isActiveFor(double y, int etag) {
return (this.etag == etag && this.activey >= y);
}
public String toString() {
return ("Edge["+curve+
", "+
(ctag == AreaOp.CTAG_LEFT ? "L" : "R")+
", "+
(etag == AreaOp.ETAG_ENTER ? "I" :
(etag == AreaOp.ETAG_EXIT ? "O" : "N"))+
"]");
}
}

View File

@@ -0,0 +1,142 @@
/*
* Copyright (c) 1998, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.geom;
import java.awt.geom.Rectangle2D;
import java.awt.geom.PathIterator;
import java.util.Vector;
final class Order0 extends Curve {
private double x;
private double y;
public Order0(double x, double y) {
super(INCREASING);
this.x = x;
this.y = y;
}
public int getOrder() {
return 0;
}
public double getXTop() {
return x;
}
public double getYTop() {
return y;
}
public double getXBot() {
return x;
}
public double getYBot() {
return y;
}
public double getXMin() {
return x;
}
public double getXMax() {
return x;
}
public double getX0() {
return x;
}
public double getY0() {
return y;
}
public double getX1() {
return x;
}
public double getY1() {
return y;
}
public double XforY(double y) {
return y;
}
public double TforY(double y) {
return 0;
}
public double XforT(double t) {
return x;
}
public double YforT(double t) {
return y;
}
public double dXforT(double t, int deriv) {
return 0;
}
public double dYforT(double t, int deriv) {
return 0;
}
public double nextVertical(double t0, double t1) {
return t1;
}
public int crossingsFor(double x, double y) {
return 0;
}
public boolean accumulateCrossings(Crossings c) {
return (x > c.getXLo() &&
x < c.getXHi() &&
y > c.getYLo() &&
y < c.getYHi());
}
public void enlarge(Rectangle2D r) {
r.add(x, y);
}
public Curve getSubCurve(double ystart, double yend, int dir) {
return this;
}
public Curve getReversedCurve() {
return this;
}
public int getSegment(double coords[]) {
coords[0] = x;
coords[1] = y;
return PathIterator.SEG_MOVETO;
}
}

View File

@@ -0,0 +1,312 @@
/*
* Copyright (c) 1998, 2006, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.geom;
import java.awt.geom.Rectangle2D;
import java.awt.geom.PathIterator;
import java.util.Vector;
final class Order1 extends Curve {
private double x0;
private double y0;
private double x1;
private double y1;
private double xmin;
private double xmax;
public Order1(double x0, double y0,
double x1, double y1,
int direction)
{
super(direction);
this.x0 = x0;
this.y0 = y0;
this.x1 = x1;
this.y1 = y1;
if (x0 < x1) {
this.xmin = x0;
this.xmax = x1;
} else {
this.xmin = x1;
this.xmax = x0;
}
}
public int getOrder() {
return 1;
}
public double getXTop() {
return x0;
}
public double getYTop() {
return y0;
}
public double getXBot() {
return x1;
}
public double getYBot() {
return y1;
}
public double getXMin() {
return xmin;
}
public double getXMax() {
return xmax;
}
public double getX0() {
return (direction == INCREASING) ? x0 : x1;
}
public double getY0() {
return (direction == INCREASING) ? y0 : y1;
}
public double getX1() {
return (direction == DECREASING) ? x0 : x1;
}
public double getY1() {
return (direction == DECREASING) ? y0 : y1;
}
public double XforY(double y) {
if (x0 == x1 || y <= y0) {
return x0;
}
if (y >= y1) {
return x1;
}
// assert(y0 != y1); /* No horizontal lines... */
return (x0 + (y - y0) * (x1 - x0) / (y1 - y0));
}
public double TforY(double y) {
if (y <= y0) {
return 0;
}
if (y >= y1) {
return 1;
}
return (y - y0) / (y1 - y0);
}
public double XforT(double t) {
return x0 + t * (x1 - x0);
}
public double YforT(double t) {
return y0 + t * (y1 - y0);
}
public double dXforT(double t, int deriv) {
switch (deriv) {
case 0:
return x0 + t * (x1 - x0);
case 1:
return (x1 - x0);
default:
return 0;
}
}
public double dYforT(double t, int deriv) {
switch (deriv) {
case 0:
return y0 + t * (y1 - y0);
case 1:
return (y1 - y0);
default:
return 0;
}
}
public double nextVertical(double t0, double t1) {
return t1;
}
public boolean accumulateCrossings(Crossings c) {
double xlo = c.getXLo();
double ylo = c.getYLo();
double xhi = c.getXHi();
double yhi = c.getYHi();
if (xmin >= xhi) {
return false;
}
double xstart, ystart, xend, yend;
if (y0 < ylo) {
if (y1 <= ylo) {
return false;
}
ystart = ylo;
xstart = XforY(ylo);
} else {
if (y0 >= yhi) {
return false;
}
ystart = y0;
xstart = x0;
}
if (y1 > yhi) {
yend = yhi;
xend = XforY(yhi);
} else {
yend = y1;
xend = x1;
}
if (xstart >= xhi && xend >= xhi) {
return false;
}
if (xstart > xlo || xend > xlo) {
return true;
}
c.record(ystart, yend, direction);
return false;
}
public void enlarge(Rectangle2D r) {
r.add(x0, y0);
r.add(x1, y1);
}
public Curve getSubCurve(double ystart, double yend, int dir) {
if (ystart == y0 && yend == y1) {
return getWithDirection(dir);
}
if (x0 == x1) {
return new Order1(x0, ystart, x1, yend, dir);
}
double num = x0 - x1;
double denom = y0 - y1;
double xstart = (x0 + (ystart - y0) * num / denom);
double xend = (x0 + (yend - y0) * num / denom);
return new Order1(xstart, ystart, xend, yend, dir);
}
public Curve getReversedCurve() {
return new Order1(x0, y0, x1, y1, -direction);
}
public int compareTo(Curve other, double yrange[]) {
if (!(other instanceof Order1)) {
return super.compareTo(other, yrange);
}
Order1 c1 = (Order1) other;
if (yrange[1] <= yrange[0]) {
throw new InternalError("yrange already screwed up...");
}
yrange[1] = Math.min(Math.min(yrange[1], y1), c1.y1);
if (yrange[1] <= yrange[0]) {
throw new InternalError("backstepping from "+yrange[0]+" to "+yrange[1]);
}
if (xmax <= c1.xmin) {
return (xmin == c1.xmax) ? 0 : -1;
}
if (xmin >= c1.xmax) {
return 1;
}
/*
* If "this" is curve A and "other" is curve B, then...
* xA(y) = x0A + (y - y0A) (x1A - x0A) / (y1A - y0A)
* xB(y) = x0B + (y - y0B) (x1B - x0B) / (y1B - y0B)
* xA(y) == xB(y)
* x0A + (y - y0A) (x1A - x0A) / (y1A - y0A)
* == x0B + (y - y0B) (x1B - x0B) / (y1B - y0B)
* 0 == x0A (y1A - y0A) (y1B - y0B) + (y - y0A) (x1A - x0A) (y1B - y0B)
* - x0B (y1A - y0A) (y1B - y0B) - (y - y0B) (x1B - x0B) (y1A - y0A)
* 0 == (x0A - x0B) (y1A - y0A) (y1B - y0B)
* + (y - y0A) (x1A - x0A) (y1B - y0B)
* - (y - y0B) (x1B - x0B) (y1A - y0A)
* If (dxA == x1A - x0A), etc...
* 0 == (x0A - x0B) * dyA * dyB
* + (y - y0A) * dxA * dyB
* - (y - y0B) * dxB * dyA
* 0 == (x0A - x0B) * dyA * dyB
* + y * dxA * dyB - y0A * dxA * dyB
* - y * dxB * dyA + y0B * dxB * dyA
* 0 == (x0A - x0B) * dyA * dyB
* + y * dxA * dyB - y * dxB * dyA
* - y0A * dxA * dyB + y0B * dxB * dyA
* 0 == (x0A - x0B) * dyA * dyB
* + y * (dxA * dyB - dxB * dyA)
* - y0A * dxA * dyB + y0B * dxB * dyA
* y == ((x0A - x0B) * dyA * dyB
* - y0A * dxA * dyB + y0B * dxB * dyA)
* / (-(dxA * dyB - dxB * dyA))
* y == ((x0A - x0B) * dyA * dyB
* - y0A * dxA * dyB + y0B * dxB * dyA)
* / (dxB * dyA - dxA * dyB)
*/
double dxa = x1 - x0;
double dya = y1 - y0;
double dxb = c1.x1 - c1.x0;
double dyb = c1.y1 - c1.y0;
double denom = dxb * dya - dxa * dyb;
double y;
if (denom != 0) {
double num = ((x0 - c1.x0) * dya * dyb
- y0 * dxa * dyb
+ c1.y0 * dxb * dya);
y = num / denom;
if (y <= yrange[0]) {
// intersection is above us
// Use bottom-most common y for comparison
y = Math.min(y1, c1.y1);
} else {
// intersection is below the top of our range
if (y < yrange[1]) {
// If intersection is in our range, adjust valid range
yrange[1] = y;
}
// Use top-most common y for comparison
y = Math.max(y0, c1.y0);
}
} else {
// lines are parallel, choose any common y for comparison
// Note - prefer an endpoint for speed of calculating the X
// (see shortcuts in Order1.XforY())
y = Math.max(y0, c1.y0);
}
return orderof(XforY(y), c1.XforY(y));
}
public int getSegment(double coords[]) {
if (direction == INCREASING) {
coords[0] = x1;
coords[1] = y1;
} else {
coords[0] = x0;
coords[1] = y0;
}
return PathIterator.SEG_LINETO;
}
}

View File

@@ -0,0 +1,453 @@
/*
* Copyright (c) 1998, 2006, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.geom;
import java.awt.geom.Rectangle2D;
import java.awt.geom.PathIterator;
import java.awt.geom.QuadCurve2D;
import java.util.Vector;
final class Order2 extends Curve {
private double x0;
private double y0;
private double cx0;
private double cy0;
private double x1;
private double y1;
private double xmin;
private double xmax;
private double xcoeff0;
private double xcoeff1;
private double xcoeff2;
private double ycoeff0;
private double ycoeff1;
private double ycoeff2;
public static void insert(Vector curves, double tmp[],
double x0, double y0,
double cx0, double cy0,
double x1, double y1,
int direction)
{
int numparams = getHorizontalParams(y0, cy0, y1, tmp);
if (numparams == 0) {
// We are using addInstance here to avoid inserting horisontal
// segments
addInstance(curves, x0, y0, cx0, cy0, x1, y1, direction);
return;
}
// assert(numparams == 1);
double t = tmp[0];
tmp[0] = x0; tmp[1] = y0;
tmp[2] = cx0; tmp[3] = cy0;
tmp[4] = x1; tmp[5] = y1;
split(tmp, 0, t);
int i0 = (direction == INCREASING)? 0 : 4;
int i1 = 4 - i0;
addInstance(curves, tmp[i0], tmp[i0 + 1], tmp[i0 + 2], tmp[i0 + 3],
tmp[i0 + 4], tmp[i0 + 5], direction);
addInstance(curves, tmp[i1], tmp[i1 + 1], tmp[i1 + 2], tmp[i1 + 3],
tmp[i1 + 4], tmp[i1 + 5], direction);
}
public static void addInstance(Vector curves,
double x0, double y0,
double cx0, double cy0,
double x1, double y1,
int direction) {
if (y0 > y1) {
curves.add(new Order2(x1, y1, cx0, cy0, x0, y0, -direction));
} else if (y1 > y0) {
curves.add(new Order2(x0, y0, cx0, cy0, x1, y1, direction));
}
}
/*
* Return the count of the number of horizontal sections of the
* specified quadratic Bezier curve. Put the parameters for the
* horizontal sections into the specified <code>ret</code> array.
* <p>
* If we examine the parametric equation in t, we have:
* Py(t) = C0*(1-t)^2 + 2*CP*t*(1-t) + C1*t^2
* = C0 - 2*C0*t + C0*t^2 + 2*CP*t - 2*CP*t^2 + C1*t^2
* = C0 + (2*CP - 2*C0)*t + (C0 - 2*CP + C1)*t^2
* Py(t) = (C0 - 2*CP + C1)*t^2 + (2*CP - 2*C0)*t + (C0)
* If we take the derivative, we get:
* Py(t) = At^2 + Bt + C
* dPy(t) = 2At + B = 0
* 2*(C0 - 2*CP + C1)t + 2*(CP - C0) = 0
* 2*(C0 - 2*CP + C1)t = 2*(C0 - CP)
* t = 2*(C0 - CP) / 2*(C0 - 2*CP + C1)
* t = (C0 - CP) / (C0 - CP + C1 - CP)
* Note that this method will return 0 if the equation is a line,
* which is either always horizontal or never horizontal.
* Completely horizontal curves need to be eliminated by other
* means outside of this method.
*/
public static int getHorizontalParams(double c0, double cp, double c1,
double ret[]) {
if (c0 <= cp && cp <= c1) {
return 0;
}
c0 -= cp;
c1 -= cp;
double denom = c0 + c1;
// If denom == 0 then cp == (c0+c1)/2 and we have a line.
if (denom == 0) {
return 0;
}
double t = c0 / denom;
// No splits at t==0 and t==1
if (t <= 0 || t >= 1) {
return 0;
}
ret[0] = t;
return 1;
}
/*
* Split the quadratic Bezier stored at coords[pos...pos+5] representing
* the paramtric range [0..1] into two subcurves representing the
* parametric subranges [0..t] and [t..1]. Store the results back
* into the array at coords[pos...pos+5] and coords[pos+4...pos+9].
*/
public static void split(double coords[], int pos, double t) {
double x0, y0, cx, cy, x1, y1;
coords[pos+8] = x1 = coords[pos+4];
coords[pos+9] = y1 = coords[pos+5];
cx = coords[pos+2];
cy = coords[pos+3];
x1 = cx + (x1 - cx) * t;
y1 = cy + (y1 - cy) * t;
x0 = coords[pos+0];
y0 = coords[pos+1];
x0 = x0 + (cx - x0) * t;
y0 = y0 + (cy - y0) * t;
cx = x0 + (x1 - x0) * t;
cy = y0 + (y1 - y0) * t;
coords[pos+2] = x0;
coords[pos+3] = y0;
coords[pos+4] = cx;
coords[pos+5] = cy;
coords[pos+6] = x1;
coords[pos+7] = y1;
}
public Order2(double x0, double y0,
double cx0, double cy0,
double x1, double y1,
int direction)
{
super(direction);
// REMIND: Better accuracy in the root finding methods would
// ensure that cy0 is in range. As it stands, it is never
// more than "1 mantissa bit" out of range...
if (cy0 < y0) {
cy0 = y0;
} else if (cy0 > y1) {
cy0 = y1;
}
this.x0 = x0;
this.y0 = y0;
this.cx0 = cx0;
this.cy0 = cy0;
this.x1 = x1;
this.y1 = y1;
xmin = Math.min(Math.min(x0, x1), cx0);
xmax = Math.max(Math.max(x0, x1), cx0);
xcoeff0 = x0;
xcoeff1 = cx0 + cx0 - x0 - x0;
xcoeff2 = x0 - cx0 - cx0 + x1;
ycoeff0 = y0;
ycoeff1 = cy0 + cy0 - y0 - y0;
ycoeff2 = y0 - cy0 - cy0 + y1;
}
public int getOrder() {
return 2;
}
public double getXTop() {
return x0;
}
public double getYTop() {
return y0;
}
public double getXBot() {
return x1;
}
public double getYBot() {
return y1;
}
public double getXMin() {
return xmin;
}
public double getXMax() {
return xmax;
}
public double getX0() {
return (direction == INCREASING) ? x0 : x1;
}
public double getY0() {
return (direction == INCREASING) ? y0 : y1;
}
public double getCX0() {
return cx0;
}
public double getCY0() {
return cy0;
}
public double getX1() {
return (direction == DECREASING) ? x0 : x1;
}
public double getY1() {
return (direction == DECREASING) ? y0 : y1;
}
public double XforY(double y) {
if (y <= y0) {
return x0;
}
if (y >= y1) {
return x1;
}
return XforT(TforY(y));
}
public double TforY(double y) {
if (y <= y0) {
return 0;
}
if (y >= y1) {
return 1;
}
return TforY(y, ycoeff0, ycoeff1, ycoeff2);
}
public static double TforY(double y,
double ycoeff0, double ycoeff1, double ycoeff2)
{
// The caller should have already eliminated y values
// outside of the y0 to y1 range.
ycoeff0 -= y;
if (ycoeff2 == 0.0) {
// The quadratic parabola has degenerated to a line.
// ycoeff1 should not be 0.0 since we have already eliminated
// totally horizontal lines, but if it is, then we will generate
// infinity here for the root, which will not be in the [0,1]
// range so we will pass to the failure code below.
double root = -ycoeff0 / ycoeff1;
if (root >= 0 && root <= 1) {
return root;
}
} else {
// From Numerical Recipes, 5.6, Quadratic and Cubic Equations
double d = ycoeff1 * ycoeff1 - 4.0 * ycoeff2 * ycoeff0;
// If d < 0.0, then there are no roots
if (d >= 0.0) {
d = Math.sqrt(d);
// For accuracy, calculate one root using:
// (-ycoeff1 +/- d) / 2ycoeff2
// and the other using:
// 2ycoeff0 / (-ycoeff1 +/- d)
// Choose the sign of the +/- so that ycoeff1+d
// gets larger in magnitude
if (ycoeff1 < 0.0) {
d = -d;
}
double q = (ycoeff1 + d) / -2.0;
// We already tested ycoeff2 for being 0 above
double root = q / ycoeff2;
if (root >= 0 && root <= 1) {
return root;
}
if (q != 0.0) {
root = ycoeff0 / q;
if (root >= 0 && root <= 1) {
return root;
}
}
}
}
/* We failed to find a root in [0,1]. What could have gone wrong?
* First, remember that these curves are constructed to be monotonic
* in Y and totally horizontal curves have already been eliminated.
* Now keep in mind that the Y coefficients of the polynomial form
* of the curve are calculated from the Y coordinates which define
* our curve. They should theoretically define the same curve,
* but they can be off by a couple of bits of precision after the
* math is done and so can represent a slightly modified curve.
* This is normally not an issue except when we have solutions near
* the endpoints. Since the answers we get from solving the polynomial
* may be off by a few bits that means that they could lie just a
* few bits of precision outside the [0,1] range.
*
* Another problem could be that while the parametric curve defined
* by the Y coordinates has a local minima or maxima at or just
* outside of the endpoints, the polynomial form might express
* that same min/max just inside of and just shy of the Y coordinate
* of that endpoint. In that case, if we solve for a Y coordinate
* at or near that endpoint, we may be solving for a Y coordinate
* that is below that minima or above that maxima and we would find
* no solutions at all.
*
* In either case, we can assume that y is so near one of the
* endpoints that we can just collapse it onto the nearest endpoint
* without losing more than a couple of bits of precision.
*/
// First calculate the midpoint between y0 and y1 and choose to
// return either 0.0 or 1.0 depending on whether y is above
// or below the midpoint...
// Note that we subtracted y from ycoeff0 above so both y0 and y1
// will be "relative to y" so we are really just looking at where
// zero falls with respect to the "relative midpoint" here.
double y0 = ycoeff0;
double y1 = ycoeff0 + ycoeff1 + ycoeff2;
return (0 < (y0 + y1) / 2) ? 0.0 : 1.0;
}
public double XforT(double t) {
return (xcoeff2 * t + xcoeff1) * t + xcoeff0;
}
public double YforT(double t) {
return (ycoeff2 * t + ycoeff1) * t + ycoeff0;
}
public double dXforT(double t, int deriv) {
switch (deriv) {
case 0:
return (xcoeff2 * t + xcoeff1) * t + xcoeff0;
case 1:
return 2 * xcoeff2 * t + xcoeff1;
case 2:
return 2 * xcoeff2;
default:
return 0;
}
}
public double dYforT(double t, int deriv) {
switch (deriv) {
case 0:
return (ycoeff2 * t + ycoeff1) * t + ycoeff0;
case 1:
return 2 * ycoeff2 * t + ycoeff1;
case 2:
return 2 * ycoeff2;
default:
return 0;
}
}
public double nextVertical(double t0, double t1) {
double t = -xcoeff1 / (2 * xcoeff2);
if (t > t0 && t < t1) {
return t;
}
return t1;
}
public void enlarge(Rectangle2D r) {
r.add(x0, y0);
double t = -xcoeff1 / (2 * xcoeff2);
if (t > 0 && t < 1) {
r.add(XforT(t), YforT(t));
}
r.add(x1, y1);
}
public Curve getSubCurve(double ystart, double yend, int dir) {
double t0, t1;
if (ystart <= y0) {
if (yend >= y1) {
return getWithDirection(dir);
}
t0 = 0;
} else {
t0 = TforY(ystart, ycoeff0, ycoeff1, ycoeff2);
}
if (yend >= y1) {
t1 = 1;
} else {
t1 = TforY(yend, ycoeff0, ycoeff1, ycoeff2);
}
double eqn[] = new double[10];
eqn[0] = x0;
eqn[1] = y0;
eqn[2] = cx0;
eqn[3] = cy0;
eqn[4] = x1;
eqn[5] = y1;
if (t1 < 1) {
split(eqn, 0, t1);
}
int i;
if (t0 <= 0) {
i = 0;
} else {
split(eqn, 0, t0 / t1);
i = 4;
}
return new Order2(eqn[i+0], ystart,
eqn[i+2], eqn[i+3],
eqn[i+4], yend,
dir);
}
public Curve getReversedCurve() {
return new Order2(x0, y0, cx0, cy0, x1, y1, -direction);
}
public int getSegment(double coords[]) {
coords[0] = cx0;
coords[1] = cy0;
if (direction == INCREASING) {
coords[2] = x1;
coords[3] = y1;
} else {
coords[2] = x0;
coords[3] = y0;
}
return PathIterator.SEG_QUADTO;
}
public String controlPointString() {
return ("("+round(cx0)+", "+round(cy0)+"), ");
}
}

View File

@@ -0,0 +1,634 @@
/*
* Copyright (c) 1998, 2006, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.geom;
import java.awt.geom.Rectangle2D;
import java.awt.geom.PathIterator;
import java.awt.geom.QuadCurve2D;
import java.util.Vector;
final class Order3 extends Curve {
private double x0;
private double y0;
private double cx0;
private double cy0;
private double cx1;
private double cy1;
private double x1;
private double y1;
private double xmin;
private double xmax;
private double xcoeff0;
private double xcoeff1;
private double xcoeff2;
private double xcoeff3;
private double ycoeff0;
private double ycoeff1;
private double ycoeff2;
private double ycoeff3;
public static void insert(Vector curves, double tmp[],
double x0, double y0,
double cx0, double cy0,
double cx1, double cy1,
double x1, double y1,
int direction)
{
int numparams = getHorizontalParams(y0, cy0, cy1, y1, tmp);
if (numparams == 0) {
// We are using addInstance here to avoid inserting horisontal
// segments
addInstance(curves, x0, y0, cx0, cy0, cx1, cy1, x1, y1, direction);
return;
}
// Store coordinates for splitting at tmp[3..10]
tmp[3] = x0; tmp[4] = y0;
tmp[5] = cx0; tmp[6] = cy0;
tmp[7] = cx1; tmp[8] = cy1;
tmp[9] = x1; tmp[10] = y1;
double t = tmp[0];
if (numparams > 1 && t > tmp[1]) {
// Perform a "2 element sort"...
tmp[0] = tmp[1];
tmp[1] = t;
t = tmp[0];
}
split(tmp, 3, t);
if (numparams > 1) {
// Recalculate tmp[1] relative to the range [tmp[0]...1]
t = (tmp[1] - t) / (1 - t);
split(tmp, 9, t);
}
int index = 3;
if (direction == DECREASING) {
index += numparams * 6;
}
while (numparams >= 0) {
addInstance(curves,
tmp[index + 0], tmp[index + 1],
tmp[index + 2], tmp[index + 3],
tmp[index + 4], tmp[index + 5],
tmp[index + 6], tmp[index + 7],
direction);
numparams--;
if (direction == INCREASING) {
index += 6;
} else {
index -= 6;
}
}
}
public static void addInstance(Vector curves,
double x0, double y0,
double cx0, double cy0,
double cx1, double cy1,
double x1, double y1,
int direction) {
if (y0 > y1) {
curves.add(new Order3(x1, y1, cx1, cy1, cx0, cy0, x0, y0,
-direction));
} else if (y1 > y0) {
curves.add(new Order3(x0, y0, cx0, cy0, cx1, cy1, x1, y1,
direction));
}
}
/*
* Return the count of the number of horizontal sections of the
* specified cubic Bezier curve. Put the parameters for the
* horizontal sections into the specified <code>ret</code> array.
* <p>
* If we examine the parametric equation in t, we have:
* Py(t) = C0(1-t)^3 + 3CP0 t(1-t)^2 + 3CP1 t^2(1-t) + C1 t^3
* = C0 - 3C0t + 3C0t^2 - C0t^3 +
* 3CP0t - 6CP0t^2 + 3CP0t^3 +
* 3CP1t^2 - 3CP1t^3 +
* C1t^3
* Py(t) = (C1 - 3CP1 + 3CP0 - C0) t^3 +
* (3C0 - 6CP0 + 3CP1) t^2 +
* (3CP0 - 3C0) t +
* (C0)
* If we take the derivative, we get:
* Py(t) = Dt^3 + At^2 + Bt + C
* dPy(t) = 3Dt^2 + 2At + B = 0
* 0 = 3*(C1 - 3*CP1 + 3*CP0 - C0)t^2
* + 2*(3*CP1 - 6*CP0 + 3*C0)t
* + (3*CP0 - 3*C0)
* 0 = 3*(C1 - 3*CP1 + 3*CP0 - C0)t^2
* + 3*2*(CP1 - 2*CP0 + C0)t
* + 3*(CP0 - C0)
* 0 = (C1 - CP1 - CP1 - CP1 + CP0 + CP0 + CP0 - C0)t^2
* + 2*(CP1 - CP0 - CP0 + C0)t
* + (CP0 - C0)
* 0 = (C1 - CP1 + CP0 - CP1 + CP0 - CP1 + CP0 - C0)t^2
* + 2*(CP1 - CP0 - CP0 + C0)t
* + (CP0 - C0)
* 0 = ((C1 - CP1) - (CP1 - CP0) - (CP1 - CP0) + (CP0 - C0))t^2
* + 2*((CP1 - CP0) - (CP0 - C0))t
* + (CP0 - C0)
* Note that this method will return 0 if the equation is a line,
* which is either always horizontal or never horizontal.
* Completely horizontal curves need to be eliminated by other
* means outside of this method.
*/
public static int getHorizontalParams(double c0, double cp0,
double cp1, double c1,
double ret[]) {
if (c0 <= cp0 && cp0 <= cp1 && cp1 <= c1) {
return 0;
}
c1 -= cp1;
cp1 -= cp0;
cp0 -= c0;
ret[0] = cp0;
ret[1] = (cp1 - cp0) * 2;
ret[2] = (c1 - cp1 - cp1 + cp0);
int numroots = QuadCurve2D.solveQuadratic(ret, ret);
int j = 0;
for (int i = 0; i < numroots; i++) {
double t = ret[i];
// No splits at t==0 and t==1
if (t > 0 && t < 1) {
if (j < i) {
ret[j] = t;
}
j++;
}
}
return j;
}
/*
* Split the cubic Bezier stored at coords[pos...pos+7] representing
* the parametric range [0..1] into two subcurves representing the
* parametric subranges [0..t] and [t..1]. Store the results back
* into the array at coords[pos...pos+7] and coords[pos+6...pos+13].
*/
public static void split(double coords[], int pos, double t) {
double x0, y0, cx0, cy0, cx1, cy1, x1, y1;
coords[pos+12] = x1 = coords[pos+6];
coords[pos+13] = y1 = coords[pos+7];
cx1 = coords[pos+4];
cy1 = coords[pos+5];
x1 = cx1 + (x1 - cx1) * t;
y1 = cy1 + (y1 - cy1) * t;
x0 = coords[pos+0];
y0 = coords[pos+1];
cx0 = coords[pos+2];
cy0 = coords[pos+3];
x0 = x0 + (cx0 - x0) * t;
y0 = y0 + (cy0 - y0) * t;
cx0 = cx0 + (cx1 - cx0) * t;
cy0 = cy0 + (cy1 - cy0) * t;
cx1 = cx0 + (x1 - cx0) * t;
cy1 = cy0 + (y1 - cy0) * t;
cx0 = x0 + (cx0 - x0) * t;
cy0 = y0 + (cy0 - y0) * t;
coords[pos+2] = x0;
coords[pos+3] = y0;
coords[pos+4] = cx0;
coords[pos+5] = cy0;
coords[pos+6] = cx0 + (cx1 - cx0) * t;
coords[pos+7] = cy0 + (cy1 - cy0) * t;
coords[pos+8] = cx1;
coords[pos+9] = cy1;
coords[pos+10] = x1;
coords[pos+11] = y1;
}
public Order3(double x0, double y0,
double cx0, double cy0,
double cx1, double cy1,
double x1, double y1,
int direction)
{
super(direction);
// REMIND: Better accuracy in the root finding methods would
// ensure that cys are in range. As it stands, they are never
// more than "1 mantissa bit" out of range...
if (cy0 < y0) cy0 = y0;
if (cy1 > y1) cy1 = y1;
this.x0 = x0;
this.y0 = y0;
this.cx0 = cx0;
this.cy0 = cy0;
this.cx1 = cx1;
this.cy1 = cy1;
this.x1 = x1;
this.y1 = y1;
xmin = Math.min(Math.min(x0, x1), Math.min(cx0, cx1));
xmax = Math.max(Math.max(x0, x1), Math.max(cx0, cx1));
xcoeff0 = x0;
xcoeff1 = (cx0 - x0) * 3.0;
xcoeff2 = (cx1 - cx0 - cx0 + x0) * 3.0;
xcoeff3 = x1 - (cx1 - cx0) * 3.0 - x0;
ycoeff0 = y0;
ycoeff1 = (cy0 - y0) * 3.0;
ycoeff2 = (cy1 - cy0 - cy0 + y0) * 3.0;
ycoeff3 = y1 - (cy1 - cy0) * 3.0 - y0;
YforT1 = YforT2 = YforT3 = y0;
}
public int getOrder() {
return 3;
}
public double getXTop() {
return x0;
}
public double getYTop() {
return y0;
}
public double getXBot() {
return x1;
}
public double getYBot() {
return y1;
}
public double getXMin() {
return xmin;
}
public double getXMax() {
return xmax;
}
public double getX0() {
return (direction == INCREASING) ? x0 : x1;
}
public double getY0() {
return (direction == INCREASING) ? y0 : y1;
}
public double getCX0() {
return (direction == INCREASING) ? cx0 : cx1;
}
public double getCY0() {
return (direction == INCREASING) ? cy0 : cy1;
}
public double getCX1() {
return (direction == DECREASING) ? cx0 : cx1;
}
public double getCY1() {
return (direction == DECREASING) ? cy0 : cy1;
}
public double getX1() {
return (direction == DECREASING) ? x0 : x1;
}
public double getY1() {
return (direction == DECREASING) ? y0 : y1;
}
private double TforY1;
private double YforT1;
private double TforY2;
private double YforT2;
private double TforY3;
private double YforT3;
/*
* Solve the cubic whose coefficients are in the a,b,c,d fields and
* return the first root in the range [0, 1].
* The cubic solved is represented by the equation:
* x^3 + (ycoeff2)x^2 + (ycoeff1)x + (ycoeff0) = y
* @return the first valid root (in the range [0, 1])
*/
public double TforY(double y) {
if (y <= y0) return 0;
if (y >= y1) return 1;
if (y == YforT1) return TforY1;
if (y == YforT2) return TforY2;
if (y == YforT3) return TforY3;
// From Numerical Recipes, 5.6, Quadratic and Cubic Equations
if (ycoeff3 == 0.0) {
// The cubic degenerated to quadratic (or line or ...).
return Order2.TforY(y, ycoeff0, ycoeff1, ycoeff2);
}
double a = ycoeff2 / ycoeff3;
double b = ycoeff1 / ycoeff3;
double c = (ycoeff0 - y) / ycoeff3;
int roots = 0;
double Q = (a * a - 3.0 * b) / 9.0;
double R = (2.0 * a * a * a - 9.0 * a * b + 27.0 * c) / 54.0;
double R2 = R * R;
double Q3 = Q * Q * Q;
double a_3 = a / 3.0;
double t;
if (R2 < Q3) {
double theta = Math.acos(R / Math.sqrt(Q3));
Q = -2.0 * Math.sqrt(Q);
t = refine(a, b, c, y, Q * Math.cos(theta / 3.0) - a_3);
if (t < 0) {
t = refine(a, b, c, y,
Q * Math.cos((theta + Math.PI * 2.0)/ 3.0) - a_3);
}
if (t < 0) {
t = refine(a, b, c, y,
Q * Math.cos((theta - Math.PI * 2.0)/ 3.0) - a_3);
}
} else {
boolean neg = (R < 0.0);
double S = Math.sqrt(R2 - Q3);
if (neg) {
R = -R;
}
double A = Math.pow(R + S, 1.0 / 3.0);
if (!neg) {
A = -A;
}
double B = (A == 0.0) ? 0.0 : (Q / A);
t = refine(a, b, c, y, (A + B) - a_3);
}
if (t < 0) {
//throw new InternalError("bad t");
double t0 = 0;
double t1 = 1;
while (true) {
t = (t0 + t1) / 2;
if (t == t0 || t == t1) {
break;
}
double yt = YforT(t);
if (yt < y) {
t0 = t;
} else if (yt > y) {
t1 = t;
} else {
break;
}
}
}
if (t >= 0) {
TforY3 = TforY2;
YforT3 = YforT2;
TforY2 = TforY1;
YforT2 = YforT1;
TforY1 = t;
YforT1 = y;
}
return t;
}
public double refine(double a, double b, double c,
double target, double t)
{
if (t < -0.1 || t > 1.1) {
return -1;
}
double y = YforT(t);
double t0, t1;
if (y < target) {
t0 = t;
t1 = 1;
} else {
t0 = 0;
t1 = t;
}
double origt = t;
double origy = y;
boolean useslope = true;
while (y != target) {
if (!useslope) {
double t2 = (t0 + t1) / 2;
if (t2 == t0 || t2 == t1) {
break;
}
t = t2;
} else {
double slope = dYforT(t, 1);
if (slope == 0) {
useslope = false;
continue;
}
double t2 = t + ((target - y) / slope);
if (t2 == t || t2 <= t0 || t2 >= t1) {
useslope = false;
continue;
}
t = t2;
}
y = YforT(t);
if (y < target) {
t0 = t;
} else if (y > target) {
t1 = t;
} else {
break;
}
}
boolean verbose = false;
if (false && t >= 0 && t <= 1) {
y = YforT(t);
long tdiff = diffbits(t, origt);
long ydiff = diffbits(y, origy);
long yerr = diffbits(y, target);
if (yerr > 0 || (verbose && tdiff > 0)) {
System.out.println("target was y = "+target);
System.out.println("original was y = "+origy+", t = "+origt);
System.out.println("final was y = "+y+", t = "+t);
System.out.println("t diff is "+tdiff);
System.out.println("y diff is "+ydiff);
System.out.println("y error is "+yerr);
double tlow = prev(t);
double ylow = YforT(tlow);
double thi = next(t);
double yhi = YforT(thi);
if (Math.abs(target - ylow) < Math.abs(target - y) ||
Math.abs(target - yhi) < Math.abs(target - y))
{
System.out.println("adjacent y's = ["+ylow+", "+yhi+"]");
}
}
}
return (t > 1) ? -1 : t;
}
public double XforY(double y) {
if (y <= y0) {
return x0;
}
if (y >= y1) {
return x1;
}
return XforT(TforY(y));
}
public double XforT(double t) {
return (((xcoeff3 * t) + xcoeff2) * t + xcoeff1) * t + xcoeff0;
}
public double YforT(double t) {
return (((ycoeff3 * t) + ycoeff2) * t + ycoeff1) * t + ycoeff0;
}
public double dXforT(double t, int deriv) {
switch (deriv) {
case 0:
return (((xcoeff3 * t) + xcoeff2) * t + xcoeff1) * t + xcoeff0;
case 1:
return ((3 * xcoeff3 * t) + 2 * xcoeff2) * t + xcoeff1;
case 2:
return (6 * xcoeff3 * t) + 2 * xcoeff2;
case 3:
return 6 * xcoeff3;
default:
return 0;
}
}
public double dYforT(double t, int deriv) {
switch (deriv) {
case 0:
return (((ycoeff3 * t) + ycoeff2) * t + ycoeff1) * t + ycoeff0;
case 1:
return ((3 * ycoeff3 * t) + 2 * ycoeff2) * t + ycoeff1;
case 2:
return (6 * ycoeff3 * t) + 2 * ycoeff2;
case 3:
return 6 * ycoeff3;
default:
return 0;
}
}
public double nextVertical(double t0, double t1) {
double eqn[] = {xcoeff1, 2 * xcoeff2, 3 * xcoeff3};
int numroots = QuadCurve2D.solveQuadratic(eqn, eqn);
for (int i = 0; i < numroots; i++) {
if (eqn[i] > t0 && eqn[i] < t1) {
t1 = eqn[i];
}
}
return t1;
}
public void enlarge(Rectangle2D r) {
r.add(x0, y0);
double eqn[] = {xcoeff1, 2 * xcoeff2, 3 * xcoeff3};
int numroots = QuadCurve2D.solveQuadratic(eqn, eqn);
for (int i = 0; i < numroots; i++) {
double t = eqn[i];
if (t > 0 && t < 1) {
r.add(XforT(t), YforT(t));
}
}
r.add(x1, y1);
}
public Curve getSubCurve(double ystart, double yend, int dir) {
if (ystart <= y0 && yend >= y1) {
return getWithDirection(dir);
}
double eqn[] = new double[14];
double t0, t1;
t0 = TforY(ystart);
t1 = TforY(yend);
eqn[0] = x0;
eqn[1] = y0;
eqn[2] = cx0;
eqn[3] = cy0;
eqn[4] = cx1;
eqn[5] = cy1;
eqn[6] = x1;
eqn[7] = y1;
if (t0 > t1) {
/* This happens in only rare cases where ystart is
* very near yend and solving for the yend root ends
* up stepping slightly lower in t than solving for
* the ystart root.
* Ideally we might want to skip this tiny little
* segment and just fudge the surrounding coordinates
* to bridge the gap left behind, but there is no way
* to do that from here. Higher levels could
* potentially eliminate these tiny "fixup" segments,
* but not without a lot of extra work on the code that
* coalesces chains of curves into subpaths. The
* simplest solution for now is to just reorder the t
* values and chop out a miniscule curve piece.
*/
double t = t0;
t0 = t1;
t1 = t;
}
if (t1 < 1) {
split(eqn, 0, t1);
}
int i;
if (t0 <= 0) {
i = 0;
} else {
split(eqn, 0, t0 / t1);
i = 6;
}
return new Order3(eqn[i+0], ystart,
eqn[i+2], eqn[i+3],
eqn[i+4], eqn[i+5],
eqn[i+6], yend,
dir);
}
public Curve getReversedCurve() {
return new Order3(x0, y0, cx0, cy0, cx1, cy1, x1, y1, -direction);
}
public int getSegment(double coords[]) {
if (direction == INCREASING) {
coords[0] = cx0;
coords[1] = cy0;
coords[2] = cx1;
coords[3] = cy1;
coords[4] = x1;
coords[5] = y1;
} else {
coords[0] = cx1;
coords[1] = cy1;
coords[2] = cx0;
coords[3] = cy0;
coords[4] = x0;
coords[5] = y0;
}
return PathIterator.SEG_CUBICTO;
}
public String controlPointString() {
return (("("+round(getCX0())+", "+round(getCY0())+"), ")+
("("+round(getCX1())+", "+round(getCY1())+"), "));
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 2007, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.geom;
public interface PathConsumer2D {
/**
* @see java.awt.geom.Path2D.Float.moveTo
*/
public void moveTo(float x, float y);
/**
* @see java.awt.geom.Path2D.Float.lineTo
*/
public void lineTo(float x, float y);
/**
* @see java.awt.geom.Path2D.Float.quadTo
*/
public void quadTo(float x1, float y1,
float x2, float y2);
/**
* @see java.awt.geom.Path2D.Float.curveTo
*/
public void curveTo(float x1, float y1,
float x2, float y2,
float x3, float y3);
/**
* @see java.awt.geom.Path2D.Float.closePath
*/
public void closePath();
/**
* Called after the last segment of the last subpath when the
* iteration of the path segments is completely done. This
* method serves to trigger the end of path processing in the
* consumer that would normally be triggered when a
* {@link java.awt.geom.PathIterator PathIterator}
* returns {@code true} from its {@code done} method.
*/
public void pathDone();
/**
* If a given PathConsumer performs all or most of its work
* natively then it can return a (non-zero) pointer to a
* native function vector that defines C functions for all
* of the above methods.
* The specific pointer it returns is a pointer to a
* PathConsumerVec structure as defined in the include file
* src/share/native/sun/java2d/pipe/PathConsumer2D.h
* @return a native pointer to a PathConsumerVec structure.
*/
public long getNativeConsumer();
}

View File

@@ -0,0 +1,319 @@
/*
* Copyright (c) 1997, 2011, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.im;
import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.InputMethodEvent;
import java.awt.event.InputMethodListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowAdapter;
import java.awt.font.FontRenderContext;
import java.awt.font.TextHitInfo;
import java.awt.font.TextLayout;
import java.awt.geom.Rectangle2D;
import java.awt.im.InputMethodRequests;
import java.text.AttributedCharacterIterator;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
/**
* A composition area is used to display text that's being composed
* using an input method in its own user interface environment,
* typically in a root window.
*
* @author JavaSoft International
*/
// This class is final due to the 6607310 fix. Refer to the CR for details.
public final class CompositionArea extends JPanel implements InputMethodListener {
private CompositionAreaHandler handler;
private TextLayout composedTextLayout;
private TextHitInfo caret = null;
private JFrame compositionWindow;
private final static int TEXT_ORIGIN_X = 5;
private final static int TEXT_ORIGIN_Y = 15;
private final static int PASSIVE_WIDTH = 480;
private final static int WIDTH_MARGIN=10;
private final static int HEIGHT_MARGIN=3;
CompositionArea() {
// create composition window with localized title
String windowTitle = Toolkit.getProperty("AWT.CompositionWindowTitle", "Input Window");
compositionWindow =
(JFrame)InputMethodContext.createInputMethodWindow(windowTitle, null, true);
setOpaque(true);
setBorder(LineBorder.createGrayLineBorder());
setForeground(Color.black);
setBackground(Color.white);
// if we get the focus, we still want to let the client's
// input context handle the event
enableInputMethods(true);
enableEvents(AWTEvent.KEY_EVENT_MASK);
compositionWindow.getContentPane().add(this);
compositionWindow.addWindowListener(new FrameWindowAdapter());
addInputMethodListener(this);
compositionWindow.enableInputMethods(false);
compositionWindow.pack();
Dimension windowSize = compositionWindow.getSize();
Dimension screenSize = (getToolkit()).getScreenSize();
compositionWindow.setLocation(screenSize.width - windowSize.width-20,
screenSize.height - windowSize.height-100);
compositionWindow.setVisible(false);
}
/**
* Sets the composition area handler that currently owns this
* composition area, and its input context.
*/
synchronized void setHandlerInfo(CompositionAreaHandler handler, InputContext inputContext) {
this.handler = handler;
((InputMethodWindow) compositionWindow).setInputContext(inputContext);
}
/**
* @see java.awt.Component#getInputMethodRequests
*/
public InputMethodRequests getInputMethodRequests() {
return handler;
}
// returns a 0-width rectangle
private Rectangle getCaretRectangle(TextHitInfo caret) {
int caretLocation = 0;
TextLayout layout = composedTextLayout;
if (layout != null) {
caretLocation = Math.round(layout.getCaretInfo(caret)[0]);
}
Graphics g = getGraphics();
FontMetrics metrics = null;
try {
metrics = g.getFontMetrics();
} finally {
g.dispose();
}
return new Rectangle(TEXT_ORIGIN_X + caretLocation,
TEXT_ORIGIN_Y - metrics.getAscent(),
0, metrics.getAscent() + metrics.getDescent());
}
public void paint(Graphics g) {
super.paint(g);
g.setColor(getForeground());
TextLayout layout = composedTextLayout;
if (layout != null) {
layout.draw((Graphics2D) g, TEXT_ORIGIN_X, TEXT_ORIGIN_Y);
}
if (caret != null) {
Rectangle rectangle = getCaretRectangle(caret);
g.setXORMode(getBackground());
g.fillRect(rectangle.x, rectangle.y, 1, rectangle.height);
g.setPaintMode();
}
}
// shows/hides the composition window
void setCompositionAreaVisible(boolean visible) {
compositionWindow.setVisible(visible);
}
// returns true if composition area is visible
boolean isCompositionAreaVisible() {
return compositionWindow.isVisible();
}
// workaround for the Solaris focus lost problem
class FrameWindowAdapter extends WindowAdapter {
public void windowActivated(WindowEvent e) {
requestFocus();
}
}
// InputMethodListener methods - just forward to the current handler
public void inputMethodTextChanged(InputMethodEvent event) {
handler.inputMethodTextChanged(event);
}
public void caretPositionChanged(InputMethodEvent event) {
handler.caretPositionChanged(event);
}
/**
* Sets the text and caret to be displayed in this composition area.
* Shows the window if it contains text, hides it if not.
*/
void setText(AttributedCharacterIterator composedText, TextHitInfo caret) {
composedTextLayout = null;
if (composedText == null) {
// there's no composed text to display, so hide the window
compositionWindow.setVisible(false);
this.caret = null;
} else {
/* since we have composed text, make sure the window is shown.
This is necessary to get a valid graphics object. See 6181385.
*/
if (!compositionWindow.isVisible()) {
compositionWindow.setVisible(true);
}
Graphics g = getGraphics();
if (g == null) {
return;
}
try {
updateWindowLocation();
FontRenderContext context = ((Graphics2D)g).getFontRenderContext();
composedTextLayout = new TextLayout(composedText, context);
Rectangle2D bounds = composedTextLayout.getBounds();
this.caret = caret;
// Resize the composition area to just fit the text.
FontMetrics metrics = g.getFontMetrics();
Rectangle2D maxCharBoundsRec = metrics.getMaxCharBounds(g);
int newHeight = (int)maxCharBoundsRec.getHeight() + HEIGHT_MARGIN;
int newFrameHeight = newHeight +compositionWindow.getInsets().top
+compositionWindow.getInsets().bottom;
// If it's a passive client, set the width always to PASSIVE_WIDTH (480px)
InputMethodRequests req = handler.getClientInputMethodRequests();
int newWidth = (req==null) ? PASSIVE_WIDTH : (int)bounds.getWidth() + WIDTH_MARGIN;
int newFrameWidth = newWidth + compositionWindow.getInsets().left
+ compositionWindow.getInsets().right;
setPreferredSize(new Dimension(newWidth, newHeight));
compositionWindow.setSize(new Dimension(newFrameWidth, newFrameHeight));
// show the composed text
paint(g);
}
finally {
g.dispose();
}
}
}
/**
* Sets the caret to be displayed in this composition area.
* The text is not changed.
*/
void setCaret(TextHitInfo caret) {
this.caret = caret;
if (compositionWindow.isVisible()) {
Graphics g = getGraphics();
try {
paint(g);
} finally {
g.dispose();
}
}
}
/**
* Positions the composition window near (usually below) the
* insertion point in the client component if the client
* component is an active client (below-the-spot input).
*/
void updateWindowLocation() {
InputMethodRequests req = handler.getClientInputMethodRequests();
if (req == null) {
// not an active client
return;
}
Point windowLocation = new Point();
Rectangle caretRect = req.getTextLocation(null);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension windowSize = compositionWindow.getSize();
final int SPACING = 2;
if (caretRect.x + windowSize.width > screenSize.width) {
windowLocation.x = screenSize.width - windowSize.width;
} else {
windowLocation.x = caretRect.x;
}
if (caretRect.y + caretRect.height + SPACING + windowSize.height > screenSize.height) {
windowLocation.y = caretRect.y - SPACING - windowSize.height;
} else {
windowLocation.y = caretRect.y + caretRect.height + SPACING;
}
compositionWindow.setLocation(windowLocation);
}
// support for InputMethodRequests methods
Rectangle getTextLocation(TextHitInfo offset) {
Rectangle rectangle = getCaretRectangle(offset);
Point location = getLocationOnScreen();
rectangle.translate(location.x, location.y);
return rectangle;
}
TextHitInfo getLocationOffset(int x, int y) {
TextLayout layout = composedTextLayout;
if (layout == null) {
return null;
} else {
Point location = getLocationOnScreen();
x -= location.x + TEXT_ORIGIN_X;
y -= location.y + TEXT_ORIGIN_Y;
if (layout.getBounds().contains(x, y)) {
return layout.hitTestChar(x, y);
} else {
return null;
}
}
}
// Disables or enables decorations of the composition window
void setCompositionAreaUndecorated(boolean setUndecorated){
if (compositionWindow.isDisplayable()){
compositionWindow.removeNotify();
}
compositionWindow.setUndecorated(setUndecorated);
compositionWindow.pack();
}
// Proclaim serial compatibility with 1.7.0
private static final long serialVersionUID = -1057247068746557444L;
}

View File

@@ -0,0 +1,354 @@
/*
* Copyright (c) 1999, 2013, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.im;
import java.awt.Component;
import java.awt.Container;
import java.awt.Rectangle;
import java.awt.event.InputMethodEvent;
import java.awt.event.InputMethodListener;
import java.awt.font.TextAttribute;
import java.awt.font.TextHitInfo;
import java.awt.im.InputMethodRequests;
import java.lang.ref.WeakReference;
import java.text.AttributedCharacterIterator;
import java.text.AttributedCharacterIterator.Attribute;
import java.text.AttributedString;
/**
* A composition area handler handles events and input method requests for
* the composition area. Typically each input method context has its own
* composition area handler if it supports passive clients or below-the-spot
* input, but all handlers share a single composition area.
*
* @author JavaSoft International
*/
class CompositionAreaHandler implements InputMethodListener,
InputMethodRequests {
private static CompositionArea compositionArea;
private static Object compositionAreaLock = new Object();
private static CompositionAreaHandler compositionAreaOwner; // synchronized through compositionArea
private AttributedCharacterIterator composedText;
private TextHitInfo caret = null;
private WeakReference<Component> clientComponent = new WeakReference<>(null);
private InputMethodContext inputMethodContext;
/**
* Constructs the composition area handler.
*/
CompositionAreaHandler(InputMethodContext context) {
inputMethodContext = context;
}
/**
* Creates the composition area.
*/
private void createCompositionArea() {
synchronized(compositionAreaLock) {
compositionArea = new CompositionArea();
if (compositionAreaOwner != null) {
compositionArea.setHandlerInfo(compositionAreaOwner, inputMethodContext);
}
// If the client component is an active client using below-the-spot style, then
// make the composition window undecorated without a title bar.
Component client = clientComponent.get();
if(client != null){
InputMethodRequests req = client.getInputMethodRequests();
if (req != null && inputMethodContext.useBelowTheSpotInput()) {
setCompositionAreaUndecorated(true);
}
}
}
}
void setClientComponent(Component clientComponent) {
this.clientComponent = new WeakReference<>(clientComponent);
}
/**
* Grabs the composition area, makes this handler its owner, and installs
* the handler and its input context into the composition area for event
* and input method request handling.
* If doUpdate is true, updates the composition area with previously sent
* composed text.
*/
void grabCompositionArea(boolean doUpdate) {
synchronized (compositionAreaLock) {
if (compositionAreaOwner != this) {
compositionAreaOwner = this;
if (compositionArea != null) {
compositionArea.setHandlerInfo(this, inputMethodContext);
}
if (doUpdate) {
// Create the composition area if necessary
if ((composedText != null) && (compositionArea == null)) {
createCompositionArea();
}
if (compositionArea != null) {
compositionArea.setText(composedText, caret);
}
}
}
}
}
/**
* Releases and closes the composition area if it is currently owned by
* this composition area handler.
*/
void releaseCompositionArea() {
synchronized (compositionAreaLock) {
if (compositionAreaOwner == this) {
compositionAreaOwner = null;
if (compositionArea != null) {
compositionArea.setHandlerInfo(null, null);
compositionArea.setText(null, null);
}
}
}
}
/**
* Releases and closes the composition area if it has been created,
* independent of the current owner.
*/
static void closeCompositionArea() {
if (compositionArea != null) {
synchronized (compositionAreaLock) {
compositionAreaOwner = null;
compositionArea.setHandlerInfo(null, null);
compositionArea.setText(null, null);
}
}
}
/**
* Returns whether the composition area is currently visible
*/
boolean isCompositionAreaVisible() {
if (compositionArea != null) {
return compositionArea.isCompositionAreaVisible();
}
return false;
}
/**
* Shows or hides the composition Area
*/
void setCompositionAreaVisible(boolean visible) {
if (compositionArea != null) {
compositionArea.setCompositionAreaVisible(visible);
}
}
void processInputMethodEvent(InputMethodEvent event) {
if (event.getID() == InputMethodEvent.INPUT_METHOD_TEXT_CHANGED) {
inputMethodTextChanged(event);
} else {
caretPositionChanged(event);
}
}
/**
* set the compositionArea frame decoration
*/
void setCompositionAreaUndecorated(boolean undecorated) {
if (compositionArea != null) {
compositionArea.setCompositionAreaUndecorated(undecorated);
}
}
//
// InputMethodListener methods
//
private static final Attribute[] IM_ATTRIBUTES =
{ TextAttribute.INPUT_METHOD_HIGHLIGHT };
public void inputMethodTextChanged(InputMethodEvent event) {
AttributedCharacterIterator text = event.getText();
int committedCharacterCount = event.getCommittedCharacterCount();
// extract composed text and prepare it for display
composedText = null;
caret = null;
if (text != null
&& committedCharacterCount < text.getEndIndex() - text.getBeginIndex()) {
// Create the composition area if necessary
if (compositionArea == null) {
createCompositionArea();
}
// copy the composed text
AttributedString composedTextString;
composedTextString = new AttributedString(text,
text.getBeginIndex() + committedCharacterCount, // skip over committed text
text.getEndIndex(), IM_ATTRIBUTES);
composedTextString.addAttribute(TextAttribute.FONT, compositionArea.getFont());
composedText = composedTextString.getIterator();
caret = event.getCaret();
}
if (compositionArea != null) {
compositionArea.setText(composedText, caret);
}
// send any committed text to the text component
if (committedCharacterCount > 0) {
inputMethodContext.dispatchCommittedText(((Component) event.getSource()),
text, committedCharacterCount);
// this may have changed the text location, so reposition the window
if (isCompositionAreaVisible()) {
compositionArea.updateWindowLocation();
}
}
// event has been handled, so consume it
event.consume();
}
public void caretPositionChanged(InputMethodEvent event) {
if (compositionArea != null) {
compositionArea.setCaret(event.getCaret());
}
// event has been handled, so consume it
event.consume();
}
//
// InputMethodRequests methods
//
/**
* Returns the input method request handler of the client component.
* When using the composition window for an active client (below-the-spot
* input), input method requests that do not relate to the display of
* the composed text are forwarded to the client component.
*/
InputMethodRequests getClientInputMethodRequests() {
Component client = clientComponent.get();
if (client != null) {
return client.getInputMethodRequests();
}
return null;
}
public Rectangle getTextLocation(TextHitInfo offset) {
synchronized (compositionAreaLock) {
if (compositionAreaOwner == this && isCompositionAreaVisible()) {
return compositionArea.getTextLocation(offset);
} else if (composedText != null) {
// there's composed text, but it's not displayed, so fake a rectangle
return new Rectangle(0, 0, 0, 10);
} else {
InputMethodRequests requests = getClientInputMethodRequests();
if (requests != null) {
return requests.getTextLocation(offset);
} else {
// passive client, no composed text, so fake a rectangle
return new Rectangle(0, 0, 0, 10);
}
}
}
}
public TextHitInfo getLocationOffset(int x, int y) {
synchronized (compositionAreaLock) {
if (compositionAreaOwner == this && isCompositionAreaVisible()) {
return compositionArea.getLocationOffset(x, y);
} else {
return null;
}
}
}
public int getInsertPositionOffset() {
InputMethodRequests req = getClientInputMethodRequests();
if (req != null) {
return req.getInsertPositionOffset();
}
// we don't have access to the client component's text.
return 0;
}
private static final AttributedCharacterIterator EMPTY_TEXT =
(new AttributedString("")).getIterator();
public AttributedCharacterIterator getCommittedText(int beginIndex,
int endIndex,
Attribute[] attributes) {
InputMethodRequests req = getClientInputMethodRequests();
if(req != null) {
return req.getCommittedText(beginIndex, endIndex, attributes);
}
// we don't have access to the client component's text.
return EMPTY_TEXT;
}
public int getCommittedTextLength() {
InputMethodRequests req = getClientInputMethodRequests();
if(req != null) {
return req.getCommittedTextLength();
}
// we don't have access to the client component's text.
return 0;
}
public AttributedCharacterIterator cancelLatestCommittedText(Attribute[] attributes) {
InputMethodRequests req = getClientInputMethodRequests();
if(req != null) {
return req.cancelLatestCommittedText(attributes);
}
// we don't have access to the client component's text.
return null;
}
public AttributedCharacterIterator getSelectedText(Attribute[] attributes) {
InputMethodRequests req = getClientInputMethodRequests();
if(req != null) {
return req.getSelectedText(attributes);
}
// we don't have access to the client component's text.
return EMPTY_TEXT;
}
}

View File

@@ -0,0 +1,632 @@
/*
* Copyright (c) 1998, 2012, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.im;
import java.awt.AWTException;
import java.awt.CheckboxMenuItem;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.PopupMenu;
import java.awt.Menu;
import java.awt.MenuItem;
import java.awt.Toolkit;
import sun.awt.AppContext;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InvocationEvent;
import java.awt.im.spi.InputMethodDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Locale;
import java.util.ServiceLoader;
import java.util.Vector;
import java.util.Set;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
import sun.awt.InputMethodSupport;
import sun.awt.SunToolkit;
/**
* <code>ExecutableInputMethodManager</code> is the implementation of the
* <code>InputMethodManager</code> class. It is runnable as a separate
* thread in the AWT environment.&nbsp;
* <code>InputMethodManager.getInstance()</code> creates an instance of
* <code>ExecutableInputMethodManager</code> and executes it as a deamon
* thread.
*
* @see InputMethodManager
*/
class ExecutableInputMethodManager extends InputMethodManager
implements Runnable
{
// the input context that's informed about selections from the user interface
private InputContext currentInputContext;
// Menu item string for the trigger menu.
private String triggerMenuString;
// popup menu for selecting an input method
private InputMethodPopupMenu selectionMenu;
private static String selectInputMethodMenuTitle;
// locator and name of host adapter
private InputMethodLocator hostAdapterLocator;
// locators for Java input methods
private int javaInputMethodCount; // number of Java input methods found
private Vector<InputMethodLocator> javaInputMethodLocatorList;
// component that is requesting input method switch
// must be Frame or Dialog
private Component requestComponent;
// input context that is requesting input method switch
private InputContext requestInputContext;
// IM preference stuff
private static final String preferredIMNode = "/sun/awt/im/preferredInputMethod";
private static final String descriptorKey = "descriptor";
private Hashtable<String, InputMethodLocator> preferredLocatorCache = new Hashtable<>();
private Preferences userRoot;
ExecutableInputMethodManager() {
// set up host adapter locator
Toolkit toolkit = Toolkit.getDefaultToolkit();
try {
if (toolkit instanceof InputMethodSupport) {
InputMethodDescriptor hostAdapterDescriptor =
((InputMethodSupport)toolkit)
.getInputMethodAdapterDescriptor();
if (hostAdapterDescriptor != null) {
hostAdapterLocator = new InputMethodLocator(hostAdapterDescriptor, null, null);
}
}
} catch (AWTException e) {
// if we can't get a descriptor, we'll just have to do without native input methods
}
javaInputMethodLocatorList = new Vector<InputMethodLocator>();
initializeInputMethodLocatorList();
}
synchronized void initialize() {
selectInputMethodMenuTitle = Toolkit.getProperty("AWT.InputMethodSelectionMenu", "Select Input Method");
triggerMenuString = selectInputMethodMenuTitle;
}
public void run() {
// If there are no multiple input methods to choose from, wait forever
while (!hasMultipleInputMethods()) {
try {
synchronized (this) {
wait();
}
} catch (InterruptedException e) {
}
}
// Loop for processing input method change requests
while (true) {
waitForChangeRequest();
initializeInputMethodLocatorList();
try {
if (requestComponent != null) {
showInputMethodMenuOnRequesterEDT(requestComponent);
} else {
// show the popup menu within the event thread
EventQueue.invokeAndWait(new Runnable() {
public void run() {
showInputMethodMenu();
}
});
}
} catch (InterruptedException ie) {
} catch (InvocationTargetException ite) {
// should we do anything under these exceptions?
}
}
}
// Shows Input Method Menu on the EDT of requester component
// to avoid side effects. See 6544309.
private void showInputMethodMenuOnRequesterEDT(Component requester)
throws InterruptedException, InvocationTargetException {
if (requester == null){
return;
}
class AWTInvocationLock {}
Object lock = new AWTInvocationLock();
InvocationEvent event =
new InvocationEvent(requester,
new Runnable() {
public void run() {
showInputMethodMenu();
}
},
lock,
true);
AppContext requesterAppContext = SunToolkit.targetToAppContext(requester);
synchronized (lock) {
SunToolkit.postEvent(requesterAppContext, event);
while (!event.isDispatched()) {
lock.wait();
}
}
Throwable eventThrowable = event.getThrowable();
if (eventThrowable != null) {
throw new InvocationTargetException(eventThrowable);
}
}
void setInputContext(InputContext inputContext) {
if (currentInputContext != null && inputContext != null) {
// don't throw this exception until 4237852 is fixed
// throw new IllegalStateException("Can't have two active InputContext at the same time");
}
currentInputContext = inputContext;
}
public synchronized void notifyChangeRequest(Component comp) {
if (!(comp instanceof Frame || comp instanceof Dialog))
return;
// if busy with the current request, ignore this request.
if (requestComponent != null)
return;
requestComponent = comp;
notify();
}
public synchronized void notifyChangeRequestByHotKey(Component comp) {
while (!(comp instanceof Frame || comp instanceof Dialog)) {
if (comp == null) {
// no Frame or Dialog found in containment hierarchy.
return;
}
comp = comp.getParent();
}
notifyChangeRequest(comp);
}
public String getTriggerMenuString() {
return triggerMenuString;
}
/*
* Returns true if the environment indicates there are multiple input methods
*/
boolean hasMultipleInputMethods() {
return ((hostAdapterLocator != null) && (javaInputMethodCount > 0)
|| (javaInputMethodCount > 1));
}
private synchronized void waitForChangeRequest() {
try {
while (requestComponent == null) {
wait();
}
} catch (InterruptedException e) {
}
}
/*
* initializes the input method locator list for all
* installed input method descriptors.
*/
private void initializeInputMethodLocatorList() {
synchronized (javaInputMethodLocatorList) {
javaInputMethodLocatorList.clear();
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() {
for (InputMethodDescriptor descriptor :
ServiceLoader.loadInstalled(InputMethodDescriptor.class)) {
ClassLoader cl = descriptor.getClass().getClassLoader();
javaInputMethodLocatorList.add(new InputMethodLocator(descriptor, cl, null));
}
return null;
}
});
} catch (PrivilegedActionException e) {
e.printStackTrace();
}
javaInputMethodCount = javaInputMethodLocatorList.size();
}
if (hasMultipleInputMethods()) {
// initialize preferences
if (userRoot == null) {
userRoot = getUserRoot();
}
} else {
// indicate to clients not to offer the menu
triggerMenuString = null;
}
}
private void showInputMethodMenu() {
if (!hasMultipleInputMethods()) {
requestComponent = null;
return;
}
// initialize pop-up menu
selectionMenu = InputMethodPopupMenu.getInstance(requestComponent, selectInputMethodMenuTitle);
// we have to rebuild the menu each time because
// some input methods (such as IIIMP) may change
// their list of supported locales dynamically
selectionMenu.removeAll();
// get information about the currently selected input method
// ??? if there's no current input context, what's the point
// of showing the menu?
String currentSelection = getCurrentSelection();
// Add menu item for host adapter
if (hostAdapterLocator != null) {
selectionMenu.addOneInputMethodToMenu(hostAdapterLocator, currentSelection);
selectionMenu.addSeparator();
}
// Add menu items for other input methods
for (int i = 0; i < javaInputMethodLocatorList.size(); i++) {
InputMethodLocator locator = javaInputMethodLocatorList.get(i);
selectionMenu.addOneInputMethodToMenu(locator, currentSelection);
}
synchronized (this) {
selectionMenu.addToComponent(requestComponent);
requestInputContext = currentInputContext;
selectionMenu.show(requestComponent, 60, 80); // TODO: get proper x, y...
requestComponent = null;
}
}
private String getCurrentSelection() {
InputContext inputContext = currentInputContext;
if (inputContext != null) {
InputMethodLocator locator = inputContext.getInputMethodLocator();
if (locator != null) {
return locator.getActionCommandString();
}
}
return null;
}
synchronized void changeInputMethod(String choice) {
InputMethodLocator locator = null;
String inputMethodName = choice;
String localeString = null;
int index = choice.indexOf('\n');
if (index != -1) {
localeString = choice.substring(index + 1);
inputMethodName = choice.substring(0, index);
}
if (hostAdapterLocator.getActionCommandString().equals(inputMethodName)) {
locator = hostAdapterLocator;
} else {
for (int i = 0; i < javaInputMethodLocatorList.size(); i++) {
InputMethodLocator candidate = javaInputMethodLocatorList.get(i);
String name = candidate.getActionCommandString();
if (name.equals(inputMethodName)) {
locator = candidate;
break;
}
}
}
if (locator != null && localeString != null) {
String language = "", country = "", variant = "";
int postIndex = localeString.indexOf('_');
if (postIndex == -1) {
language = localeString;
} else {
language = localeString.substring(0, postIndex);
int preIndex = postIndex + 1;
postIndex = localeString.indexOf('_', preIndex);
if (postIndex == -1) {
country = localeString.substring(preIndex);
} else {
country = localeString.substring(preIndex, postIndex);
variant = localeString.substring(postIndex + 1);
}
}
Locale locale = new Locale(language, country, variant);
locator = locator.deriveLocator(locale);
}
if (locator == null)
return;
// tell the input context about the change
if (requestInputContext != null) {
requestInputContext.changeInputMethod(locator);
requestInputContext = null;
// remember the selection
putPreferredInputMethod(locator);
}
}
InputMethodLocator findInputMethod(Locale locale) {
// look for preferred input method first
InputMethodLocator locator = getPreferredInputMethod(locale);
if (locator != null) {
return locator;
}
if (hostAdapterLocator != null && hostAdapterLocator.isLocaleAvailable(locale)) {
return hostAdapterLocator.deriveLocator(locale);
}
// Update the locator list
initializeInputMethodLocatorList();
for (int i = 0; i < javaInputMethodLocatorList.size(); i++) {
InputMethodLocator candidate = javaInputMethodLocatorList.get(i);
if (candidate.isLocaleAvailable(locale)) {
return candidate.deriveLocator(locale);
}
}
return null;
}
Locale getDefaultKeyboardLocale() {
Toolkit toolkit = Toolkit.getDefaultToolkit();
if (toolkit instanceof InputMethodSupport) {
return ((InputMethodSupport)toolkit).getDefaultKeyboardLocale();
} else {
return Locale.getDefault();
}
}
/**
* Returns a InputMethodLocator object that the
* user prefers for the given locale.
*
* @param locale Locale for which the user prefers the input method.
*/
private synchronized InputMethodLocator getPreferredInputMethod(Locale locale) {
InputMethodLocator preferredLocator = null;
if (!hasMultipleInputMethods()) {
// No need to look for a preferred Java input method
return null;
}
// look for the cached preference first.
preferredLocator = preferredLocatorCache.get(locale.toString().intern());
if (preferredLocator != null) {
return preferredLocator;
}
// look for the preference in the user preference tree
String nodePath = findPreferredInputMethodNode(locale);
String descriptorName = readPreferredInputMethod(nodePath);
Locale advertised;
// get the locator object
if (descriptorName != null) {
// check for the host adapter first
if (hostAdapterLocator != null &&
hostAdapterLocator.getDescriptor().getClass().getName().equals(descriptorName)) {
advertised = getAdvertisedLocale(hostAdapterLocator, locale);
if (advertised != null) {
preferredLocator = hostAdapterLocator.deriveLocator(advertised);
preferredLocatorCache.put(locale.toString().intern(), preferredLocator);
}
return preferredLocator;
}
// look for Java input methods
for (int i = 0; i < javaInputMethodLocatorList.size(); i++) {
InputMethodLocator locator = javaInputMethodLocatorList.get(i);
InputMethodDescriptor descriptor = locator.getDescriptor();
if (descriptor.getClass().getName().equals(descriptorName)) {
advertised = getAdvertisedLocale(locator, locale);
if (advertised != null) {
preferredLocator = locator.deriveLocator(advertised);
preferredLocatorCache.put(locale.toString().intern(), preferredLocator);
}
return preferredLocator;
}
}
// maybe preferred input method information is bogus.
writePreferredInputMethod(nodePath, null);
}
return null;
}
private String findPreferredInputMethodNode(Locale locale) {
if (userRoot == null) {
return null;
}
// create locale node relative path
String nodePath = preferredIMNode + "/" + createLocalePath(locale);
// look for the descriptor
while (!nodePath.equals(preferredIMNode)) {
try {
if (userRoot.nodeExists(nodePath)) {
if (readPreferredInputMethod(nodePath) != null) {
return nodePath;
}
}
} catch (BackingStoreException bse) {
}
// search at parent's node
nodePath = nodePath.substring(0, nodePath.lastIndexOf('/'));
}
return null;
}
private String readPreferredInputMethod(String nodePath) {
if ((userRoot == null) || (nodePath == null)) {
return null;
}
return userRoot.node(nodePath).get(descriptorKey, null);
}
/**
* Writes the preferred input method descriptor class name into
* the user's Preferences tree in accordance with the given locale.
*
* @param inputMethodLocator input method locator to remember.
*/
private synchronized void putPreferredInputMethod(InputMethodLocator locator) {
InputMethodDescriptor descriptor = locator.getDescriptor();
Locale preferredLocale = locator.getLocale();
if (preferredLocale == null) {
// check available locales of the input method
try {
Locale[] availableLocales = descriptor.getAvailableLocales();
if (availableLocales.length == 1) {
preferredLocale = availableLocales[0];
} else {
// there is no way to know which locale is the preferred one, so do nothing.
return;
}
} catch (AWTException ae) {
// do nothing here, either.
return;
}
}
// for regions that have only one language, we need to regard
// "xx_YY" as "xx" when putting the preference into tree
if (preferredLocale.equals(Locale.JAPAN)) {
preferredLocale = Locale.JAPANESE;
}
if (preferredLocale.equals(Locale.KOREA)) {
preferredLocale = Locale.KOREAN;
}
if (preferredLocale.equals(new Locale("th", "TH"))) {
preferredLocale = new Locale("th");
}
// obtain node
String path = preferredIMNode + "/" + createLocalePath(preferredLocale);
// write in the preference tree
writePreferredInputMethod(path, descriptor.getClass().getName());
preferredLocatorCache.put(preferredLocale.toString().intern(),
locator.deriveLocator(preferredLocale));
return;
}
private String createLocalePath(Locale locale) {
String language = locale.getLanguage();
String country = locale.getCountry();
String variant = locale.getVariant();
String localePath = null;
if (!variant.equals("")) {
localePath = "_" + language + "/_" + country + "/_" + variant;
} else if (!country.equals("")) {
localePath = "_" + language + "/_" + country;
} else {
localePath = "_" + language;
}
return localePath;
}
private void writePreferredInputMethod(String path, String descriptorName) {
if (userRoot != null) {
Preferences node = userRoot.node(path);
// record it
if (descriptorName != null) {
node.put(descriptorKey, descriptorName);
} else {
node.remove(descriptorKey);
}
}
}
private Preferences getUserRoot() {
return AccessController.doPrivileged(new PrivilegedAction<Preferences>() {
public Preferences run() {
return Preferences.userRoot();
}
});
}
private Locale getAdvertisedLocale(InputMethodLocator locator, Locale locale) {
Locale advertised = null;
if (locator.isLocaleAvailable(locale)) {
advertised = locale;
} else if (locale.getLanguage().equals("ja")) {
// for Japanese, Korean, and Thai, check whether the input method supports
// language or language_COUNTRY.
if (locator.isLocaleAvailable(Locale.JAPAN)) {
advertised = Locale.JAPAN;
} else if (locator.isLocaleAvailable(Locale.JAPANESE)) {
advertised = Locale.JAPANESE;
}
} else if (locale.getLanguage().equals("ko")) {
if (locator.isLocaleAvailable(Locale.KOREA)) {
advertised = Locale.KOREA;
} else if (locator.isLocaleAvailable(Locale.KOREAN)) {
advertised = Locale.KOREAN;
}
} else if (locale.getLanguage().equals("th")) {
if (locator.isLocaleAvailable(new Locale("th", "TH"))) {
advertised = new Locale("th", "TH");
} else if (locator.isLocaleAvailable(new Locale("th"))) {
advertised = new Locale("th");
}
}
return advertised;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,117 @@
/*
* Copyright (c) 1997, 2012, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.im;
import java.awt.Component;
import java.awt.Rectangle;
import java.awt.im.spi.InputMethod;
/**
* An input method adapter interfaces with the native input methods
* on a host platform. In general, it looks to the input method
* framework like a Java input method (that may support a few more
* locales than a typical Java input method). However, since it
* often has to work in a slightly hostile environment that's not
* designed for easy integration into the Java input method
* framework, it gets some special treatment that's not available
* to Java input methods.
* <p>
* Licensees are free to modify this class as necessary to implement
* their host input method adapters.
*
* @author JavaSoft International
*/
public abstract class InputMethodAdapter implements InputMethod {
private Component clientComponent;
void setClientComponent(Component client) {
clientComponent = client;
}
protected Component getClientComponent() {
return clientComponent;
}
protected boolean haveActiveClient() {
return clientComponent != null && clientComponent.getInputMethodRequests() != null;
}
/**
* Informs the input method adapter about the component that has the AWT
* focus if it's using the input context owning this adapter instance.
*/
protected void setAWTFocussedComponent(Component component) {
// ignore - adapters can override if needed
}
/**
* Returns whether host input methods can support below-the-spot input.
* Returns false by default.
*/
protected boolean supportsBelowTheSpot() {
return false;
}
/**
* Informs the input method adapter not to listen to the native events.
*/
protected void stopListening() {
// ignore - adapters can override if needed
}
/**
* Notifies client Window location or status changes
*/
public void notifyClientWindowChange(Rectangle location) {
}
/**
* Starts reconvertion. An implementing host adapter has to override
* this method if it can support reconvert().
* @exception UnsupportedOperationException when the adapter does not override
* the method.
*/
public void reconvert() {
throw new UnsupportedOperationException();
}
/**
* Disable the native input method. This method is provided for explicitly
* turning off the native IM. The native IM is not turned off
* when the native input method is deactivated. This method is
* always called on AWT EDT. See details in bug 6226489.
*/
public abstract void disableInputMethod();
/**
* Returns a string with information about the native input method, or
* null.
*/
public abstract String getNativeInputMethodInfo();
}

View File

@@ -0,0 +1,377 @@
/*
* Copyright (c) 1997, 2011, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.im;
import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.KeyEvent;
import java.awt.event.InputMethodEvent;
import java.awt.font.TextHitInfo;
import java.awt.im.InputMethodRequests;
import java.awt.im.spi.InputMethod;
import java.security.AccessController;
import java.text.AttributedCharacterIterator;
import java.text.AttributedCharacterIterator.Attribute;
import java.text.AttributedString;
import java.text.CharacterIterator;
import javax.swing.JFrame;
import sun.awt.InputMethodSupport;
import sun.security.action.GetPropertyAction;
/**
* The InputMethodContext class provides methods that input methods
* can use to communicate with their client components.
* It is a subclass of InputContext, which provides methods for use by
* components.
*
* @author JavaSoft International
*/
public class InputMethodContext
extends sun.awt.im.InputContext
implements java.awt.im.spi.InputMethodContext {
private boolean dispatchingCommittedText;
// Creation of the context's composition area handler is
// delayed until we really need a composition area.
private CompositionAreaHandler compositionAreaHandler;
private Object compositionAreaHandlerLock = new Object();
static private boolean belowTheSpotInputRequested;
private boolean inputMethodSupportsBelowTheSpot;
static {
// check whether we should use below-the-spot input
// get property from command line
String inputStyle = AccessController.doPrivileged
(new GetPropertyAction("java.awt.im.style", null));
// get property from awt.properties file
if (inputStyle == null) {
inputStyle = Toolkit.getProperty("java.awt.im.style", null);
}
belowTheSpotInputRequested = "below-the-spot".equals(inputStyle);
}
/**
* Constructs an InputMethodContext.
*/
public InputMethodContext() {
super();
}
void setInputMethodSupportsBelowTheSpot(boolean supported) {
inputMethodSupportsBelowTheSpot = supported;
}
boolean useBelowTheSpotInput() {
return belowTheSpotInputRequested && inputMethodSupportsBelowTheSpot;
}
private boolean haveActiveClient() {
Component client = getClientComponent();
return client != null
&& client.getInputMethodRequests() != null;
}
// implements java.awt.im.spi.InputMethodContext.dispatchInputMethodEvent
public void dispatchInputMethodEvent(int id,
AttributedCharacterIterator text, int committedCharacterCount,
TextHitInfo caret, TextHitInfo visiblePosition) {
// We need to record the client component as the source so
// that we have correct information if we later have to break up this
// event into key events.
Component source;
source = getClientComponent();
if (source != null) {
InputMethodEvent event = new InputMethodEvent(source,
id, text, committedCharacterCount, caret, visiblePosition);
if (haveActiveClient() && !useBelowTheSpotInput()) {
source.dispatchEvent(event);
} else {
getCompositionAreaHandler(true).processInputMethodEvent(event);
}
}
}
/**
* Dispatches committed text to a client component.
* Called by composition window.
*
* @param client The component that the text should get dispatched to.
* @param text The iterator providing access to the committed
* (and possible composed) text.
* @param committedCharacterCount The number of committed characters in the text.
*/
synchronized void dispatchCommittedText(Component client,
AttributedCharacterIterator text,
int committedCharacterCount) {
// note that the client is not always the current client component -
// some host input method adapters may dispatch input method events
// through the Java event queue, and we may have switched clients while
// the event was in the queue.
if (committedCharacterCount == 0
|| text.getEndIndex() <= text.getBeginIndex()) {
return;
}
long time = System.currentTimeMillis();
dispatchingCommittedText = true;
try {
InputMethodRequests req = client.getInputMethodRequests();
if (req != null) {
// active client -> send text as InputMethodEvent
int beginIndex = text.getBeginIndex();
AttributedCharacterIterator toBeCommitted =
(new AttributedString(text, beginIndex, beginIndex + committedCharacterCount)).getIterator();
InputMethodEvent inputEvent = new InputMethodEvent(
client,
InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
toBeCommitted,
committedCharacterCount,
null, null);
client.dispatchEvent(inputEvent);
} else {
// passive client -> send text as KeyEvents
char keyChar = text.first();
while (committedCharacterCount-- > 0 && keyChar != CharacterIterator.DONE) {
KeyEvent keyEvent = new KeyEvent(client, KeyEvent.KEY_TYPED,
time, 0, KeyEvent.VK_UNDEFINED, keyChar);
client.dispatchEvent(keyEvent);
keyChar = text.next();
}
}
} finally {
dispatchingCommittedText = false;
}
}
public void dispatchEvent(AWTEvent event) {
// some host input method adapters may dispatch input method events
// through the Java event queue. If the component that the event is
// intended for isn't an active client, or if we're using below-the-spot
// input, we need to dispatch this event
// to the input window. Note that that component is not necessarily the
// current client component, since we may have switched clients while
// the event was in the queue.
if (event instanceof InputMethodEvent) {
if (((Component) event.getSource()).getInputMethodRequests() == null
|| (useBelowTheSpotInput() && !dispatchingCommittedText)) {
getCompositionAreaHandler(true).processInputMethodEvent((InputMethodEvent) event);
}
} else {
// make sure we don't dispatch our own key events back to the input method
if (!dispatchingCommittedText) {
super.dispatchEvent(event);
}
}
}
/**
* Gets this context's composition area handler, creating it if necessary.
* If requested, it grabs the composition area for use by this context.
* The composition area's text is not updated.
*/
private CompositionAreaHandler getCompositionAreaHandler(boolean grab) {
synchronized(compositionAreaHandlerLock) {
if (compositionAreaHandler == null) {
compositionAreaHandler = new CompositionAreaHandler(this);
}
compositionAreaHandler.setClientComponent(getClientComponent());
if (grab) {
compositionAreaHandler.grabCompositionArea(false);
}
return compositionAreaHandler;
}
}
/**
* Grabs the composition area for use by this context.
* If doUpdate is true, updates the composition area with previously sent
* composed text.
*/
void grabCompositionArea(boolean doUpdate) {
synchronized(compositionAreaHandlerLock) {
if (compositionAreaHandler != null) {
compositionAreaHandler.grabCompositionArea(doUpdate);
} else {
// if this context hasn't seen a need for a composition area yet,
// just close it without creating the machinery
CompositionAreaHandler.closeCompositionArea();
}
}
}
/**
* Releases and closes the composition area if it is currently owned by
* this context's composition area handler.
*/
void releaseCompositionArea() {
synchronized(compositionAreaHandlerLock) {
if (compositionAreaHandler != null) {
compositionAreaHandler.releaseCompositionArea();
}
}
}
/**
* Calls CompositionAreaHandler.isCompositionAreaVisible() to see
* whether the composition area is visible or not.
* Notice that this method is always called on the AWT event dispatch
* thread.
*/
boolean isCompositionAreaVisible() {
if (compositionAreaHandler != null) {
return compositionAreaHandler.isCompositionAreaVisible();
}
return false;
}
/**
* Calls CompositionAreaHandler.setCompositionAreaVisible to
* show or hide the composition area.
* As isCompositionAreaVisible method, it is always called
* on AWT event dispatch thread.
*/
void setCompositionAreaVisible(boolean visible) {
if (compositionAreaHandler != null) {
compositionAreaHandler.setCompositionAreaVisible(visible);
}
}
/**
* Calls the current client component's implementation of getTextLocation.
*/
public Rectangle getTextLocation(TextHitInfo offset) {
return getReq().getTextLocation(offset);
}
/**
* Calls the current client component's implementation of getLocationOffset.
*/
public TextHitInfo getLocationOffset(int x, int y) {
return getReq().getLocationOffset(x, y);
}
/**
* Calls the current client component's implementation of getInsertPositionOffset.
*/
public int getInsertPositionOffset() {
return getReq().getInsertPositionOffset();
}
/**
* Calls the current client component's implementation of getCommittedText.
*/
public AttributedCharacterIterator getCommittedText(int beginIndex,
int endIndex,
Attribute[] attributes) {
return getReq().getCommittedText(beginIndex, endIndex, attributes);
}
/**
* Calls the current client component's implementation of getCommittedTextLength.
*/
public int getCommittedTextLength() {
return getReq().getCommittedTextLength();
}
/**
* Calls the current client component's implementation of cancelLatestCommittedText.
*/
public AttributedCharacterIterator cancelLatestCommittedText(Attribute[] attributes) {
return getReq().cancelLatestCommittedText(attributes);
}
/**
* Calls the current client component's implementation of getSelectedText.
*/
public AttributedCharacterIterator getSelectedText(Attribute[] attributes) {
return getReq().getSelectedText(attributes);
}
private InputMethodRequests getReq() {
if (haveActiveClient() && !useBelowTheSpotInput()) {
return getClientComponent().getInputMethodRequests();
} else {
return getCompositionAreaHandler(false);
}
}
// implements java.awt.im.spi.InputMethodContext.createInputMethodWindow
public Window createInputMethodWindow(String title, boolean attachToInputContext) {
InputContext context = attachToInputContext ? this : null;
return createInputMethodWindow(title, context, false);
}
// implements java.awt.im.spi.InputMethodContext.createInputMethodJFrame
public JFrame createInputMethodJFrame(String title, boolean attachToInputContext) {
InputContext context = attachToInputContext ? this : null;
return (JFrame)createInputMethodWindow(title, context, true);
}
static Window createInputMethodWindow(String title, InputContext context, boolean isSwing) {
if (GraphicsEnvironment.isHeadless()) {
throw new HeadlessException();
}
if (isSwing) {
return new InputMethodJFrame(title, context);
} else {
Toolkit toolkit = Toolkit.getDefaultToolkit();
if (toolkit instanceof InputMethodSupport) {
return ((InputMethodSupport)toolkit).createInputMethodWindow(
title, context);
}
}
throw new InternalError("Input methods must be supported");
}
/**
* @see java.awt.im.spi.InputMethodContext#enableClientWindowNotification
*/
public void enableClientWindowNotification(InputMethod inputMethod, boolean enable) {
super.enableClientWindowNotification(inputMethod, enable);
}
/**
* Disables or enables decorations for the composition window.
*/
void setCompositionAreaUndecorated(boolean undecorated) {
if (compositionAreaHandler != null) {
compositionAreaHandler.setCompositionAreaUndecorated(undecorated);
}
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright (c) 2001, 2011, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.im;
import javax.swing.JFrame;
import javax.swing.JRootPane;
/**
* Implements a Swing based input method window that provides the minimal
* functionality as specified in
* {@link java.awt.im.spi.InputMethodContext#createInputMethodJFrame}.
*
*/
public class InputMethodJFrame
extends JFrame
implements InputMethodWindow {
InputContext inputContext = null;
/**
* Constructs a Swing based input method window.
*/
public InputMethodJFrame(String title, InputContext context) {
super(title);
//InputMethodJFrame never has LookAndFeel decoration
if(JFrame.isDefaultLookAndFeelDecorated())
{
this.setUndecorated(true);
this.getRootPane().setWindowDecorationStyle(JRootPane.NONE);
}
if (context != null) {
this.inputContext = context;
}
setFocusableWindowState(false);
}
public void setInputContext(InputContext inputContext) {
this.inputContext = inputContext;
}
public java.awt.im.InputContext getInputContext() {
if (inputContext != null) {
return inputContext;
} else {
return super.getInputContext();
}
}
// Proclaim serial compatibility with 1.7.0
private static final long serialVersionUID = -4705856747771842549L;
}

View File

@@ -0,0 +1,171 @@
/*
* Copyright (c) 1998, 1999, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.im;
import java.awt.AWTException;
import java.awt.im.spi.InputMethodDescriptor;
import java.util.Locale;
/**
* Provides complete information to make and handle the selection
* of an input method and a locale. Immutable class.
*/
final class InputMethodLocator {
private InputMethodDescriptor descriptor;
// Currently `loader' is always the class loader for a
// descriptor. `loader' is provided for future extensions to be
// able to load input methods from somewhere else, and to support
// per input method name space.
private ClassLoader loader;
private Locale locale;
InputMethodLocator(InputMethodDescriptor descriptor, ClassLoader loader, Locale locale) {
if (descriptor == null) {
throw new NullPointerException("descriptor can't be null");
}
this.descriptor = descriptor;
this.loader = loader;
this.locale = locale;
}
public boolean equals(Object other) {
if (other == this) {
return true;
}
if (other == null || this.getClass() != other.getClass()) {
return false;
}
InputMethodLocator otherLocator = (InputMethodLocator) other;
if (!descriptor.getClass().equals(otherLocator.descriptor.getClass())) {
return false;
}
if (loader == null && otherLocator.loader != null
|| loader != null && !loader.equals(otherLocator.loader)) {
return false;
}
if (locale == null && otherLocator.locale != null
|| locale != null && !locale.equals(otherLocator.locale)) {
return false;
}
return true;
}
public int hashCode() {
int result = descriptor.hashCode();
if (loader != null) {
result |= loader.hashCode() << 10;
}
if (locale != null) {
result |= locale.hashCode() << 20;
}
return result;
}
InputMethodDescriptor getDescriptor() {
return descriptor;
}
ClassLoader getClassLoader() {
return loader;
}
Locale getLocale() {
return locale;
}
/**
* Returns whether support for locale is available from
* the input method.
*/
boolean isLocaleAvailable(Locale locale) {
try {
Locale[] locales = descriptor.getAvailableLocales();
for (int i = 0; i < locales.length; i++) {
if (locales[i].equals(locale)) {
return true;
}
}
} catch (AWTException e) {
// treat this as no locale available
}
return false;
}
/**
* Returns an input method locator that has locale forLocale,
* but otherwise the same data as this locator. Does not
* check whether the input method actually supports forLocale -
* use {@link #isLocaleAvailable} for that.
*/
InputMethodLocator deriveLocator(Locale forLocale) {
if (forLocale == locale) {
return this;
} else {
return new InputMethodLocator(descriptor, loader, forLocale);
}
}
/**
* Returns whether this and other describe the same input method
* engine, ignoring the locale setting.
*/
boolean sameInputMethod(InputMethodLocator other) {
if (other == this) {
return true;
}
if (other == null) {
return false;
}
if (!descriptor.getClass().equals(other.descriptor.getClass())) {
return false;
}
if (loader == null && other.loader != null
|| loader != null && !loader.equals(other.loader)) {
return false;
}
return true;
}
/**
* Returns a string that can be used as an action command string.
* The first part of the string identifies the input method; it does
* not include '\n'. If getLocale is not null, getLocale().toString()
* is appended, separated by '\n'.
*/
String getActionCommandString() {
String inputMethodString = descriptor.getClass().getName();
if (locale == null) {
return inputMethodString;
} else {
return inputMethodString + "\n" + locale.toString();
}
}
}

View File

@@ -0,0 +1,231 @@
/*
* Copyright (c) 1998, 2012, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.im;
import java.awt.AWTException;
import java.awt.CheckboxMenuItem;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.PopupMenu;
import java.awt.Menu;
import java.awt.MenuItem;
import java.awt.Toolkit;
import sun.awt.AppContext;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InvocationEvent;
import java.awt.im.spi.InputMethodDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Locale;
import java.util.ServiceLoader;
import java.util.Vector;
import java.util.Set;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
import sun.awt.InputMethodSupport;
import sun.awt.SunToolkit;
/**
* <code>InputMethodManager</code> is an abstract class that manages the input
* method environment of JVM. There is only one <code>InputMethodManager</code>
* instance in JVM that is executed under a separate daemon thread.
* <code>InputMethodManager</code> performs the following:
* <UL>
* <LI>
* Keeps track of the current input context.</LI>
*
* <LI>
* Provides a user interface to switch input methods and notifies the current
* input context about changes made from the user interface.</LI>
* </UL>
*
* The mechanism for supporting input method switch is as follows. (Note that
* this may change in future releases.)
*
* <UL>
* <LI>
* One way is to use platform-dependent window manager's menu (known as the <I>Window
* menu </I>in Motif and the <I>System menu</I> or <I>Control menu</I> in
* Win32) on each window which is popped up by clicking the left top box of
* a window (known as <I>Window menu button</I> in Motif and <I>System menu
* button</I> in Win32). This happens to be common in both Motif and Win32.</LI>
*
* <LI>
* When more than one input method descriptor can be found or the only input
* method descriptor found supports multiple locales, a menu item
* is added to the window (manager) menu. This item label is obtained invoking
* <code>getTriggerMenuString()</code>. If null is returned by this method, it
* means that there is only input method or none in the environment. Frame and Dialog
* invoke this method.</LI>
*
* <LI>
* This menu item means a trigger switch to the user to pop up a selection
* menu.</LI>
*
* <LI>
* When the menu item of the window (manager) menu has been selected by the
* user, Frame/Dialog invokes <code>notifyChangeRequest()</code> to notify
* <code>InputMethodManager</code> that the user wants to switch input methods.</LI>
*
* <LI>
* <code>InputMethodManager</code> displays a pop-up menu to choose an input method.</LI>
*
* <LI>
* <code>InputMethodManager</code> notifies the current <code>InputContext</code> of
* the selected <code>InputMethod</code>.</LI>
* </UL>
*
* <UL>
* <LI>
* The other way is to use user-defined hot key combination to show the pop-up menu to
* choose an input method. This is useful for the platforms which do not provide a
* way to add a menu item in the window (manager) menu.</LI>
*
* <LI>
* When the hot key combination is typed by the user, the component which has the input
* focus invokes <code>notifyChangeRequestByHotKey()</code> to notify
* <code>InputMethodManager</code> that the user wants to switch input methods.</LI>
*
* <LI>
* This results in a popup menu and notification to the current input context,
* as above.</LI>
* </UL>
*
* @see java.awt.im.spi.InputMethod
* @see sun.awt.im.InputContext
* @see sun.awt.im.InputMethodAdapter
* @author JavaSoft International
*/
public abstract class InputMethodManager {
/**
* InputMethodManager thread name
*/
private static final String threadName = "AWT-InputMethodManager";
/**
* Object for global locking
*/
private static final Object LOCK = new Object();
/**
* The InputMethodManager instance
*/
private static InputMethodManager inputMethodManager;
/**
* Returns the instance of InputMethodManager. This method creates
* the instance that is unique in the Java VM if it has not been
* created yet.
*
* @return the InputMethodManager instance
*/
public static final InputMethodManager getInstance() {
if (inputMethodManager != null) {
return inputMethodManager;
}
synchronized(LOCK) {
if (inputMethodManager == null) {
ExecutableInputMethodManager imm = new ExecutableInputMethodManager();
// Initialize the input method manager and start a
// daemon thread if the user has multiple input methods
// to choose from. Otherwise, just keep the instance.
if (imm.hasMultipleInputMethods()) {
imm.initialize();
Thread immThread = new Thread(imm, threadName);
immThread.setDaemon(true);
immThread.setPriority(Thread.NORM_PRIORITY + 1);
immThread.start();
}
inputMethodManager = imm;
}
}
return inputMethodManager;
}
/**
* Gets a string for the trigger menu item that should be added to
* the window manager menu. If no need to display the trigger menu
* item, null is returned.
*/
public abstract String getTriggerMenuString();
/**
* Notifies InputMethodManager that input method change has been
* requested by the user. This notification triggers a popup menu
* for user selection.
*
* @param comp Component that has accepted the change
* request. This component has to be a Frame or Dialog.
*/
public abstract void notifyChangeRequest(Component comp);
/**
* Notifies InputMethodManager that input method change has been
* requested by the user using the hot key combination. This
* notification triggers a popup menu for user selection.
*
* @param comp Component that has accepted the change
* request. This component has the input focus.
*/
public abstract void notifyChangeRequestByHotKey(Component comp);
/**
* Sets the current input context so that it will be notified
* of input method changes initiated from the user interface.
* Set to real input context when activating; to null when
* deactivating.
*/
abstract void setInputContext(InputContext inputContext);
/**
* Tries to find an input method locator for the given locale.
* Returns null if no available input method locator supports
* the locale.
*/
abstract InputMethodLocator findInputMethod(Locale forLocale);
/**
* Gets the default keyboard locale of the underlying operating system.
*/
abstract Locale getDefaultKeyboardLocale();
/**
* Returns whether multiple input methods are available or not
*/
abstract boolean hasMultipleInputMethods();
}

View File

@@ -0,0 +1,275 @@
/*
* Copyright (c) 2003, 2007, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.im;
import java.awt.AWTException;
import java.awt.CheckboxMenuItem;
import java.awt.Component;
import java.awt.Container;
import java.awt.PopupMenu;
import java.awt.Menu;
import java.awt.MenuItem;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.im.spi.InputMethodDescriptor;
import java.util.Locale;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPopupMenu;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
/**
* <code>InputMethodPopupMenu</code> provides the popup selection menu
*/
abstract class InputMethodPopupMenu implements ActionListener {
// Factory method to provide the menu, depending on the client, i.e.,
// provide Swing popup menu if client is a swing app, otherwise AWT popup
// is created.
static InputMethodPopupMenu getInstance(Component client, String title) {
if ((client instanceof JFrame) ||
(client instanceof JDialog)) {
return new JInputMethodPopupMenu(title);
} else {
return new AWTInputMethodPopupMenu(title);
}
}
abstract void show(Component c, int x, int y);
abstract void removeAll();
abstract void addSeparator();
abstract void addToComponent(Component c);
abstract Object createSubmenu(String label);
abstract void add(Object menuItem);
abstract void addMenuItem(String label, String command, String currentSelection);
abstract void addMenuItem(Object targetMenu, String label, String command,
String currentSelection);
void addOneInputMethodToMenu(InputMethodLocator locator, String currentSelection) {
InputMethodDescriptor descriptor = locator.getDescriptor();
String label = descriptor.getInputMethodDisplayName(null, Locale.getDefault());
String command = locator.getActionCommandString();
Locale[] locales = null;
int localeCount;
try {
locales = descriptor.getAvailableLocales();
localeCount = locales.length;
} catch (AWTException e) {
// ??? should have better error handling -
// tell user what happened, then remove this input method from the list.
// For the time being, just show it disabled.
localeCount = 0;
}
if (localeCount == 0) {
// could be IIIMP adapter which has lost its connection
addMenuItem(label, null, currentSelection);
} else if (localeCount == 1) {
if (descriptor.hasDynamicLocaleList()) {
// try to make sure that what the user sees and what
// we eventually select is consistent even if the locale
// list changes in the meantime
label = descriptor.getInputMethodDisplayName(locales[0], Locale.getDefault());
command = locator.deriveLocator(locales[0]).getActionCommandString();
}
addMenuItem(label, command, currentSelection);
} else {
Object submenu = createSubmenu(label);
add(submenu);
for (int j = 0; j < localeCount; j++) {
Locale locale = locales[j];
String subLabel = getLocaleName(locale);
String subCommand = locator.deriveLocator(locale).getActionCommandString();
addMenuItem(submenu, subLabel, subCommand, currentSelection);
}
}
}
/**
* Returns whether command indicates the same input method as currentSelection,
* taking into account that command may not specify a locale where currentSelection does.
*/
static boolean isSelected(String command, String currentSelection) {
if (command == null || currentSelection == null) {
return false;
}
if (command.equals(currentSelection)) {
return true;
}
// currentSelection may indicate a locale where command does not
int index = currentSelection.indexOf('\n');
if (index != -1 && currentSelection.substring(0, index).equals(command)) {
return true;
}
return false;
}
/**
* Returns a localized locale name for input methods with the
* given locale. It falls back to Locale.getDisplayName() and
* then to Locale.toString() if no localized locale name is found.
*
* @param locale Locale for which localized locale name is obtained
*/
String getLocaleName(Locale locale) {
String localeString = locale.toString();
String localeName = Toolkit.getProperty("AWT.InputMethodLanguage." + localeString, null);
if (localeName == null) {
localeName = locale.getDisplayName();
if (localeName == null || localeName.length() == 0)
localeName = localeString;
}
return localeName;
}
// ActionListener implementation
public void actionPerformed(ActionEvent event) {
String choice = event.getActionCommand();
((ExecutableInputMethodManager)InputMethodManager.getInstance()).changeInputMethod(choice);
}
}
class JInputMethodPopupMenu extends InputMethodPopupMenu {
static JPopupMenu delegate = null;
JInputMethodPopupMenu(String title) {
synchronized (this) {
if (delegate == null) {
delegate = new JPopupMenu(title);
}
}
}
void show(Component c, int x, int y) {
delegate.show(c, x, y);
}
void removeAll() {
delegate.removeAll();
}
void addSeparator() {
delegate.addSeparator();
}
void addToComponent(Component c) {
}
Object createSubmenu(String label) {
return new JMenu(label);
}
void add(Object menuItem) {
delegate.add((JMenuItem)menuItem);
}
void addMenuItem(String label, String command, String currentSelection) {
addMenuItem(delegate, label, command, currentSelection);
}
void addMenuItem(Object targetMenu, String label, String command, String currentSelection) {
JMenuItem menuItem;
if (isSelected(command, currentSelection)) {
menuItem = new JCheckBoxMenuItem(label, true);
} else {
menuItem = new JMenuItem(label);
}
menuItem.setActionCommand(command);
menuItem.addActionListener(this);
menuItem.setEnabled(command != null);
if (targetMenu instanceof JMenu) {
((JMenu)targetMenu).add(menuItem);
} else {
((JPopupMenu)targetMenu).add(menuItem);
}
}
}
class AWTInputMethodPopupMenu extends InputMethodPopupMenu {
static PopupMenu delegate = null;
AWTInputMethodPopupMenu(String title) {
synchronized (this) {
if (delegate == null) {
delegate = new PopupMenu(title);
}
}
}
void show(Component c, int x, int y) {
delegate.show(c, x, y);
}
void removeAll() {
delegate.removeAll();
}
void addSeparator() {
delegate.addSeparator();
}
void addToComponent(Component c) {
c.add(delegate);
}
Object createSubmenu(String label) {
return new Menu(label);
}
void add(Object menuItem) {
delegate.add((MenuItem)menuItem);
}
void addMenuItem(String label, String command, String currentSelection) {
addMenuItem(delegate, label, command, currentSelection);
}
void addMenuItem(Object targetMenu, String label, String command, String currentSelection) {
MenuItem menuItem;
if (isSelected(command, currentSelection)) {
menuItem = new CheckboxMenuItem(label, true);
} else {
menuItem = new MenuItem(label);
}
menuItem.setActionCommand(command);
menuItem.addActionListener(this);
menuItem.setEnabled(command != null);
((Menu)targetMenu).add(menuItem);
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 1999, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.im;
/**
* Interface for input method windows that need special handling
* by input method window.
*
*/
public interface InputMethodWindow {
/**
* Sets the input context that this input method window is attached to,
* null to unattach the window.
* @see java.awt.im.spi.InputMethodContext#createInputMethodWindow
*/
public void setInputContext(InputContext inputContext);
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 1999, 2011, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.im;
import java.awt.Frame;
/**
* Implements a simple input method window that provides the minimal
* functionality as specified in
* {@link java.awt.im.spi.InputMethodContext#createInputMethodWindow}.
*
*/
public class SimpleInputMethodWindow
extends Frame
implements InputMethodWindow {
InputContext inputContext = null;
/**
* Constructs a simple input method window.
*/
public SimpleInputMethodWindow(String title, InputContext context) {
super(title);
if (context != null) {
this.inputContext = context;
}
setFocusableWindowState(false);
}
public void setInputContext(InputContext inputContext) {
this.inputContext = inputContext;
}
public java.awt.im.InputContext getInputContext() {
if (inputContext != null) {
return inputContext;
} else {
return super.getInputContext();
}
}
// Proclaim serial compatibility with 1.7.0
private static final long serialVersionUID = 5093376647036461555L;
}

View File

@@ -0,0 +1,122 @@
/*
* Copyright (c) 2014, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.image;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.*;
/**
* This class provides default implementations for the
* <code>MultiResolutionImage</code> interface. The developer needs only
* to subclass this abstract class and define the <code>getResolutionVariant</code>,
* <code>getResolutionVariants</code>, and <code>getBaseImage</code> methods.
*
*
* For example,
* {@code
* public class CustomMultiResolutionImage extends AbstractMultiResolutionImage {
*
* int baseImageIndex;
* Image[] resolutionVariants;
*
* public CustomMultiResolutionImage(int baseImageIndex,
* Image... resolutionVariants) {
* this.baseImageIndex = baseImageIndex;
* this.resolutionVariants = resolutionVariants;
* }
*
* @Override
* public Image getResolutionVariant(float logicalDPIX, float logicalDPIY,
* float baseImageWidth, float baseImageHeight,
* float destImageWidth, float destImageHeight) {
* // return a resolution variant based on the given logical DPI,
* // base image size, or destination image size
* }
*
* @Override
* public List<Image> getResolutionVariants() {
* return Arrays.asList(resolutionVariants);
* }
*
* protected Image getBaseImage() {
* return resolutionVariants[baseImageIndex];
* }
* }
* }
*
* @see java.awt.Image
* @see java.awt.image.MultiResolutionImage
*
*/
public abstract class AbstractMultiResolutionImage extends java.awt.Image
implements MultiResolutionImage {
/**
* @inheritDoc
*/
@Override
public int getWidth(ImageObserver observer) {
return getBaseImage().getWidth(null);
}
/**
* @inheritDoc
*/
@Override
public int getHeight(ImageObserver observer) {
return getBaseImage().getHeight(null);
}
/**
* @inheritDoc
*/
@Override
public ImageProducer getSource() {
return getBaseImage().getSource();
}
/**
* @inheritDoc
*/
@Override
public Graphics getGraphics() {
return getBaseImage().getGraphics();
}
/**
* @inheritDoc
*/
@Override
public Object getProperty(String name, ImageObserver observer) {
return getBaseImage().getProperty(name, observer);
}
/**
* @return base image
*/
protected abstract Image getBaseImage();
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 1995, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.image;
public class BadDepthException extends Exception {
public BadDepthException() {
}
}

View File

@@ -0,0 +1,422 @@
/*
* Copyright (c) 1999, 2018, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.image;
import java.awt.Rectangle;
import java.awt.GraphicsConfiguration;
import java.awt.image.ColorModel;
import java.awt.image.SampleModel;
import java.awt.image.DirectColorModel;
import java.awt.image.IndexColorModel;
import java.awt.image.Raster;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import sun.java2d.SurfaceData;
import sun.java2d.SunGraphics2D;
import sun.java2d.loops.SurfaceType;
import sun.java2d.loops.CompositeType;
import sun.java2d.loops.RenderLoops;
public class BufImgSurfaceData extends SurfaceData {
BufferedImage bufImg;
private BufferedImageGraphicsConfig graphicsConfig;
RenderLoops solidloops;
private static native void initIDs(Class ICM, Class ICMColorData);
private static final int DCM_RGBX_RED_MASK = 0xff000000;
private static final int DCM_RGBX_GREEN_MASK = 0x00ff0000;
private static final int DCM_RGBX_BLUE_MASK = 0x0000ff00;
private static final int DCM_555X_RED_MASK = 0xF800;
private static final int DCM_555X_GREEN_MASK = 0x07C0;
private static final int DCM_555X_BLUE_MASK = 0x003E;
private static final int DCM_4444_RED_MASK = 0x0f00;
private static final int DCM_4444_GREEN_MASK = 0x00f0;
private static final int DCM_4444_BLUE_MASK = 0x000f;
private static final int DCM_4444_ALPHA_MASK = 0xf000;
private static final int DCM_ARGBBM_ALPHA_MASK = 0x01000000;
private static final int DCM_ARGBBM_RED_MASK = 0x00ff0000;
private static final int DCM_ARGBBM_GREEN_MASK = 0x0000ff00;
private static final int DCM_ARGBBM_BLUE_MASK = 0x000000ff;
static {
initIDs(IndexColorModel.class, ICMColorData.class);
}
public static SurfaceData createData(BufferedImage bufImg) {
if (bufImg == null) {
throw new NullPointerException("BufferedImage cannot be null");
}
SurfaceData sData;
ColorModel cm = bufImg.getColorModel();
int type = bufImg.getType();
// REMIND: Check the image type and pick an appropriate subclass
switch (type) {
case BufferedImage.TYPE_INT_BGR:
sData = createDataIC(bufImg, SurfaceType.IntBgr);
break;
case BufferedImage.TYPE_INT_RGB:
sData = createDataIC(bufImg, SurfaceType.IntRgb);
break;
case BufferedImage.TYPE_INT_ARGB:
sData = createDataIC(bufImg, SurfaceType.IntArgb);
break;
case BufferedImage.TYPE_INT_ARGB_PRE:
sData = createDataIC(bufImg, SurfaceType.IntArgbPre);
break;
case BufferedImage.TYPE_3BYTE_BGR:
sData = createDataBC(bufImg, SurfaceType.ThreeByteBgr, 2);
break;
case BufferedImage.TYPE_4BYTE_ABGR:
sData = createDataBC(bufImg, SurfaceType.FourByteAbgr, 3);
break;
case BufferedImage.TYPE_4BYTE_ABGR_PRE:
sData = createDataBC(bufImg, SurfaceType.FourByteAbgrPre, 3);
break;
case BufferedImage.TYPE_USHORT_565_RGB:
sData = createDataSC(bufImg, SurfaceType.Ushort565Rgb, null);
break;
case BufferedImage.TYPE_USHORT_555_RGB:
sData = createDataSC(bufImg, SurfaceType.Ushort555Rgb, null);
break;
case BufferedImage.TYPE_BYTE_INDEXED:
{
SurfaceType sType;
switch (cm.getTransparency()) {
case OPAQUE:
if (isOpaqueGray((IndexColorModel)cm)) {
sType = SurfaceType.Index8Gray;
} else {
sType = SurfaceType.ByteIndexedOpaque;
}
break;
case BITMASK:
sType = SurfaceType.ByteIndexedBm;
break;
case TRANSLUCENT:
sType = SurfaceType.ByteIndexed;
break;
default:
throw new InternalError("Unrecognized transparency");
}
sData = createDataBC(bufImg, sType, 0);
}
break;
case BufferedImage.TYPE_BYTE_GRAY:
sData = createDataBC(bufImg, SurfaceType.ByteGray, 0);
break;
case BufferedImage.TYPE_USHORT_GRAY:
sData = createDataSC(bufImg, SurfaceType.UshortGray, null);
break;
case BufferedImage.TYPE_BYTE_BINARY:
{
SurfaceType sType;
SampleModel sm = bufImg.getRaster().getSampleModel();
switch (sm.getSampleSize(0)) {
case 1:
sType = SurfaceType.ByteBinary1Bit;
break;
case 2:
sType = SurfaceType.ByteBinary2Bit;
break;
case 4:
sType = SurfaceType.ByteBinary4Bit;
break;
default:
throw new InternalError("Unrecognized pixel size");
}
sData = createDataBP(bufImg, sType);
}
break;
case BufferedImage.TYPE_CUSTOM:
default:
{
Raster raster = bufImg.getRaster();
int numBands = raster.getNumBands();
if (raster instanceof IntegerComponentRaster &&
raster.getNumDataElements() == 1 &&
((IntegerComponentRaster)raster).getPixelStride() == 1)
{
SurfaceType sType = SurfaceType.AnyInt;
if (cm instanceof DirectColorModel) {
DirectColorModel dcm = (DirectColorModel) cm;
int aMask = dcm.getAlphaMask();
int rMask = dcm.getRedMask();
int gMask = dcm.getGreenMask();
int bMask = dcm.getBlueMask();
if (numBands == 3 &&
aMask == 0 &&
rMask == DCM_RGBX_RED_MASK &&
gMask == DCM_RGBX_GREEN_MASK &&
bMask == DCM_RGBX_BLUE_MASK)
{
sType = SurfaceType.IntRgbx;
} else if (numBands == 4 &&
aMask == DCM_ARGBBM_ALPHA_MASK &&
rMask == DCM_ARGBBM_RED_MASK &&
gMask == DCM_ARGBBM_GREEN_MASK &&
bMask == DCM_ARGBBM_BLUE_MASK)
{
sType = SurfaceType.IntArgbBm;
} else {
sType = SurfaceType.AnyDcm;
}
}
sData = createDataIC(bufImg, sType);
break;
} else if (raster instanceof ShortComponentRaster &&
raster.getNumDataElements() == 1 &&
((ShortComponentRaster)raster).getPixelStride() == 1)
{
SurfaceType sType = SurfaceType.AnyShort;
IndexColorModel icm = null;
if (cm instanceof DirectColorModel) {
DirectColorModel dcm = (DirectColorModel) cm;
int aMask = dcm.getAlphaMask();
int rMask = dcm.getRedMask();
int gMask = dcm.getGreenMask();
int bMask = dcm.getBlueMask();
if (numBands == 3 &&
aMask == 0 &&
rMask == DCM_555X_RED_MASK &&
gMask == DCM_555X_GREEN_MASK &&
bMask == DCM_555X_BLUE_MASK)
{
sType = SurfaceType.Ushort555Rgbx;
} else
if (numBands == 4 &&
aMask == DCM_4444_ALPHA_MASK &&
rMask == DCM_4444_RED_MASK &&
gMask == DCM_4444_GREEN_MASK &&
bMask == DCM_4444_BLUE_MASK)
{
sType = SurfaceType.Ushort4444Argb;
}
} else if (cm instanceof IndexColorModel) {
icm = (IndexColorModel)cm;
if (icm.getPixelSize() == 12) {
if (isOpaqueGray(icm)) {
sType = SurfaceType.Index12Gray;
} else {
sType = SurfaceType.UshortIndexed;
}
} else {
icm = null;
}
}
sData = createDataSC(bufImg, sType, icm);
break;
}
sData = new BufImgSurfaceData(raster.getDataBuffer(),
bufImg, SurfaceType.Custom);
}
break;
}
((BufImgSurfaceData) sData).initSolidLoops();
return sData;
}
public static SurfaceData createData(Raster ras, ColorModel cm) {
throw new InternalError("SurfaceData not implemented for Raster/CM");
}
public static SurfaceData createDataIC(BufferedImage bImg,
SurfaceType sType) {
IntegerComponentRaster icRaster =
(IntegerComponentRaster)bImg.getRaster();
BufImgSurfaceData bisd =
new BufImgSurfaceData(icRaster.getDataBuffer(), bImg, sType);
bisd.initRaster(icRaster.getDataStorage(),
icRaster.getDataOffset(0) * 4, 0,
icRaster.getWidth(),
icRaster.getHeight(),
icRaster.getPixelStride() * 4,
icRaster.getScanlineStride() * 4,
null);
return bisd;
}
public static SurfaceData createDataSC(BufferedImage bImg,
SurfaceType sType,
IndexColorModel icm) {
ShortComponentRaster scRaster =
(ShortComponentRaster)bImg.getRaster();
BufImgSurfaceData bisd =
new BufImgSurfaceData(scRaster.getDataBuffer(), bImg, sType);
bisd.initRaster(scRaster.getDataStorage(),
scRaster.getDataOffset(0) * 2, 0,
scRaster.getWidth(),
scRaster.getHeight(),
scRaster.getPixelStride() * 2,
scRaster.getScanlineStride() * 2,
icm);
return bisd;
}
public static SurfaceData createDataBC(BufferedImage bImg,
SurfaceType sType,
int primaryBank) {
ByteComponentRaster bcRaster =
(ByteComponentRaster)bImg.getRaster();
BufImgSurfaceData bisd =
new BufImgSurfaceData(bcRaster.getDataBuffer(), bImg, sType);
ColorModel cm = bImg.getColorModel();
IndexColorModel icm = ((cm instanceof IndexColorModel)
? (IndexColorModel) cm
: null);
bisd.initRaster(bcRaster.getDataStorage(),
bcRaster.getDataOffset(primaryBank), 0,
bcRaster.getWidth(),
bcRaster.getHeight(),
bcRaster.getPixelStride(),
bcRaster.getScanlineStride(),
icm);
return bisd;
}
public static SurfaceData createDataBP(BufferedImage bImg,
SurfaceType sType) {
BytePackedRaster bpRaster =
(BytePackedRaster)bImg.getRaster();
BufImgSurfaceData bisd =
new BufImgSurfaceData(bpRaster.getDataBuffer(), bImg, sType);
ColorModel cm = bImg.getColorModel();
IndexColorModel icm = ((cm instanceof IndexColorModel)
? (IndexColorModel) cm
: null);
bisd.initRaster(bpRaster.getDataStorage(),
bpRaster.getDataBitOffset() / 8,
bpRaster.getDataBitOffset() & 7,
bpRaster.getWidth(),
bpRaster.getHeight(),
0,
bpRaster.getScanlineStride(),
icm);
return bisd;
}
public RenderLoops getRenderLoops(SunGraphics2D sg2d) {
if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR &&
sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY)
{
return solidloops;
}
return super.getRenderLoops(sg2d);
}
public java.awt.image.Raster getRaster(int x, int y, int w, int h) {
return bufImg.getRaster();
}
/**
* Initializes the native Ops pointer.
*/
protected native void initRaster(Object theArray,
int offset,
int bitoffset,
int width,
int height,
int pixStr,
int scanStr,
IndexColorModel icm);
public BufImgSurfaceData(DataBuffer db,
BufferedImage bufImg, SurfaceType sType)
{
super(SunWritableRaster.stealTrackable(db),
sType, bufImg.getColorModel());
this.bufImg = bufImg;
}
protected BufImgSurfaceData(SurfaceType surfaceType, ColorModel cm) {
super(surfaceType, cm);
}
public void initSolidLoops() {
this.solidloops = getSolidLoops(getSurfaceType());
}
private static final int CACHE_SIZE = 5;
private static RenderLoops loopcache[] = new RenderLoops[CACHE_SIZE];
private static SurfaceType typecache[] = new SurfaceType[CACHE_SIZE];
public static synchronized RenderLoops getSolidLoops(SurfaceType type) {
for (int i = CACHE_SIZE - 1; i >= 0; i--) {
SurfaceType t = typecache[i];
if (t == type) {
return loopcache[i];
} else if (t == null) {
break;
}
}
RenderLoops l = makeRenderLoops(SurfaceType.OpaqueColor,
CompositeType.SrcNoEa,
type);
System.arraycopy(loopcache, 1, loopcache, 0, CACHE_SIZE-1);
System.arraycopy(typecache, 1, typecache, 0, CACHE_SIZE-1);
loopcache[CACHE_SIZE - 1] = l;
typecache[CACHE_SIZE - 1] = type;
return l;
}
public SurfaceData getReplacement() {
// BufImgSurfaceData objects should never lose their contents,
// so this method should never be called.
return restoreContents(bufImg);
}
public synchronized GraphicsConfiguration getDeviceConfiguration() {
if (graphicsConfig == null) {
graphicsConfig = BufferedImageGraphicsConfig.getConfig(bufImg);
}
return graphicsConfig;
}
public java.awt.Rectangle getBounds() {
return new Rectangle(bufImg.getWidth(), bufImg.getHeight());
}
protected void checkCustomComposite() {
// BufferedImages always allow Custom Composite objects since
// their pixels are immediately retrievable anyway.
}
/**
* Returns destination Image associated with this SurfaceData.
*/
public Object getDestination() {
return bufImg;
}
public static final class ICMColorData {
private long pData = 0L;
private ICMColorData(long pData) {
this.pData = pData;
}
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2007, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.image;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.ImageCapabilities;
import java.awt.image.BufferedImage;
import sun.java2d.SurfaceData;
import sun.java2d.loops.CompositeType;
/**
* This SurfaceManager variant manages the default (software) surface of a
* BufferedImage.
* All rendering to the image will use the software surface as the destination.
* This is one of the more minimalist implementations of SurfaceManager.
*/
public class BufImgSurfaceManager extends SurfaceManager {
/**
* A reference to the BufferedImage whose contents are being managed.
*/
protected BufferedImage bImg;
/**
* The default (software) surface containing the contents of the
* BufferedImage.
*/
protected SurfaceData sdDefault;
public BufImgSurfaceManager(BufferedImage bImg) {
this.bImg = bImg;
this.sdDefault = BufImgSurfaceData.createData(bImg);
}
public SurfaceData getPrimarySurfaceData() {
return sdDefault;
}
/**
* Called from platform-specific SurfaceData objects to attempt to
* auto-restore the contents of an accelerated surface that has been lost.
*/
public SurfaceData restoreContents() {
return sdDefault;
}
}

Some files were not shown because too many files have changed in this diff Show More