/* * Copyright (c) 2002, 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.X11; import java.awt.*; import java.awt.event.InputEvent; import java.awt.event.MouseEvent; import java.awt.event.KeyEvent; import java.awt.datatransfer.Clipboard; import java.awt.dnd.DragSource; import java.awt.dnd.DragGestureListener; import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragGestureRecognizer; import java.awt.dnd.MouseDragGestureRecognizer; import java.awt.dnd.InvalidDnDOperationException; import java.awt.dnd.peer.DragSourceContextPeer; import java.awt.im.InputMethodHighlight; import java.awt.im.spi.InputMethodDescriptor; import java.awt.image.ColorModel; import java.awt.peer.*; import java.beans.PropertyChangeListener; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.*; import javax.swing.LookAndFeel; import javax.swing.UIDefaults; import sun.awt.*; import sun.font.FontConfigManager; import sun.misc.PerformanceLogger; import sun.print.PrintJob2D; import sun.security.action.GetPropertyAction; import sun.security.action.GetBooleanAction; import sun.util.logging.PlatformLogger; public final class XToolkit extends UNIXToolkit implements Runnable { private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XToolkit"); private static final PlatformLogger eventLog = PlatformLogger.getLogger("sun.awt.X11.event.XToolkit"); private static final PlatformLogger timeoutTaskLog = PlatformLogger.getLogger("sun.awt.X11.timeoutTask.XToolkit"); private static final PlatformLogger keyEventLog = PlatformLogger.getLogger("sun.awt.X11.kye.XToolkit"); private static final PlatformLogger backingStoreLog = PlatformLogger.getLogger("sun.awt.X11.backingStore.XToolkit"); //There is 400 ms is set by default on Windows and 500 by default on KDE and GNOME. //We use the same hardcoded constant. private final static int AWT_MULTICLICK_DEFAULT_TIME = 500; static final boolean PRIMARY_LOOP = false; static final boolean SECONDARY_LOOP = true; private static String awtAppClassName = null; // the system clipboard - CLIPBOARD selection XClipboard clipboard; // the system selection - PRIMARY selection XClipboard selection; // Dynamic Layout Resize client code setting protected static boolean dynamicLayoutSetting = false; //Is it allowed to generate events assigned to extra mouse buttons. //Set to true by default. private static boolean areExtraMouseButtonsEnabled = true; /** * True when the x settings have been loaded. */ private boolean loadedXSettings; /** * XSETTINGS for the default screen. *
*/
private XSettings xs;
private FontConfigManager fcManager = new FontConfigManager();
static int arrowCursor;
static TreeMap winMap = new TreeMap();
static HashMap specialPeerMap = new HashMap();
static HashMap winToDispatcher = new HashMap();
private static long _display;
static UIDefaults uidefaults;
static X11GraphicsEnvironment localEnv;
static X11GraphicsDevice device;
static final X11GraphicsConfig config;
static int awt_multiclick_time;
static boolean securityWarningEnabled;
private static int screenWidth = -1, screenHeight = -1; // Dimensions of default screen
static long awt_defaultFg; // Pixel
private static XMouseInfoPeer xPeer;
static {
initSecurityWarning();
if (GraphicsEnvironment.isHeadless()) {
config = null;
} else {
localEnv = (X11GraphicsEnvironment) GraphicsEnvironment
.getLocalGraphicsEnvironment();
device = (X11GraphicsDevice) localEnv.getDefaultScreenDevice();
config = (X11GraphicsConfig) (device.getDefaultConfiguration());
if (device != null) {
_display = device.getDisplay();
}
setupModifierMap();
initIDs();
setBackingStoreType();
}
}
/*
* Return (potentially) platform specific display timeout for the
* tray icon
*/
static native long getTrayIconDisplayTimeout();
private native static void initIDs();
native static void waitForEvents(long nextTaskTime);
static Thread toolkitThread;
static boolean isToolkitThread() {
return Thread.currentThread() == toolkitThread;
}
static void initSecurityWarning() {
// Enable warning only for internal builds
String runtime = AccessController.doPrivileged(
new GetPropertyAction("java.runtime.version"));
securityWarningEnabled = (runtime != null && runtime.contains("internal"));
}
static boolean isSecurityWarningEnabled() {
return securityWarningEnabled;
}
static native void awt_output_flush();
static final void awtFUnlock() {
awtUnlock();
awt_output_flush();
}
public native void nativeLoadSystemColors(int[] systemColors);
static UIDefaults getUIDefaults() {
if (uidefaults == null) {
initUIDefaults();
}
return uidefaults;
}
public void loadSystemColors(int[] systemColors) {
nativeLoadSystemColors(systemColors);
MotifColorUtilities.loadSystemColors(systemColors);
}
static void initUIDefaults() {
try {
// Load Defaults from MotifLookAndFeel
// This dummy load is necessary to get SystemColor initialized. !!!!!!
Color c = SystemColor.text;
LookAndFeel lnf = new XAWTLookAndFeel();
uidefaults = lnf.getDefaults();
}
catch (Exception e)
{
e.printStackTrace();
}
}
static Object displayLock = new Object();
public static long getDisplay() {
return _display;
}
public static long getDefaultRootWindow() {
awtLock();
try {
long res = XlibWrapper.RootWindow(XToolkit.getDisplay(),
XlibWrapper.DefaultScreen(XToolkit.getDisplay()));
if (res == 0) {
throw new IllegalStateException("Root window must not be null");
}
return res;
} finally {
awtUnlock();
}
}
void init() {
awtLock();
try {
XlibWrapper.XSupportsLocale();
if (XlibWrapper.XSetLocaleModifiers("") == null) {
log.finer("X locale modifiers are not supported, using default");
}
tryXKB();
AwtScreenData defaultScreen = new AwtScreenData(XToolkit.getDefaultScreenData());
awt_defaultFg = defaultScreen.get_blackpixel();
arrowCursor = XlibWrapper.XCreateFontCursor(XToolkit.getDisplay(),
XCursorFontConstants.XC_arrow);
areExtraMouseButtonsEnabled = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons", "true"));
//set system property if not yet assigned
System.setProperty("sun.awt.enableExtraMouseButtons", ""+areExtraMouseButtonsEnabled);
} finally {
awtUnlock();
}
PrivilegedAction
* NB: This could be called from any thread if triggered by
*
* The methods of java.awt.Desktop class are supported on the Gnome desktop.
* Check if the running desktop is Gnome by checking the window manager.
*/
public boolean isDesktopSupported(){
return XDesktopPeer.isDesktopSupported();
}
public DesktopPeer createDesktopPeer(Desktop target){
return new XDesktopPeer();
}
public boolean areExtraMouseButtonsEnabled() throws HeadlessException {
return areExtraMouseButtonsEnabled;
}
@Override
public boolean isWindowOpacitySupported() {
XNETProtocol net_protocol = XWM.getWM().getNETProtocol();
if (net_protocol == null) {
return false;
}
return net_protocol.doOpacityProtocol();
}
@Override
public boolean isWindowShapingSupported() {
return XlibUtil.isShapingSupported();
}
@Override
public boolean isWindowTranslucencySupported() {
//NOTE: it may not be supported. The actual check is being performed
// at com.sun.awt.AWTUtilities(). In X11 we need to check
// whether there's any translucency-capable GC available.
return true;
}
@Override
public boolean isTranslucencyCapable(GraphicsConfiguration gc) {
if (!(gc instanceof X11GraphicsConfig)) {
return false;
}
return ((X11GraphicsConfig)gc).isTranslucencyCapable();
}
/**
* Returns the value of "sun.awt.disablegrab" property. Default
* value is {@code false}.
*/
public static boolean getSunAwtDisableGrab() {
return AccessController.doPrivileged(new GetBooleanAction("sun.awt.disablegrab"));
}
}
p
.
* @return true, if there is remembered last cursor position,
* false otherwise
*/
boolean getLastCursorPos(Point p) {
awtLock();
try {
if (lastCursorPos == null) {
return false;
}
p.setLocation(lastCursorPos);
return true;
} finally {
awtUnlock();
}
}
private void processGlobalMotionEvent(XEvent e) {
// Only our windows guaranteely generate MotionNotify, so we
// should track enter/leave, to catch the moment when to
// switch to XQueryPointer
if (e.get_type() == XConstants.MotionNotify) {
XMotionEvent ev = e.get_xmotion();
awtLock();
try {
if (lastCursorPos == null) {
lastCursorPos = new Point(ev.get_x_root(), ev.get_y_root());
} else {
lastCursorPos.setLocation(ev.get_x_root(), ev.get_y_root());
}
} finally {
awtUnlock();
}
} else if (e.get_type() == XConstants.LeaveNotify) {
// Leave from our window
awtLock();
try {
lastCursorPos = null;
} finally {
awtUnlock();
}
} else if (e.get_type() == XConstants.EnterNotify) {
// Entrance into our window
XCrossingEvent ev = e.get_xcrossing();
awtLock();
try {
if (lastCursorPos == null) {
lastCursorPos = new Point(ev.get_x_root(), ev.get_y_root());
} else {
lastCursorPos.setLocation(ev.get_x_root(), ev.get_y_root());
}
} finally {
awtUnlock();
}
}
}
public interface XEventListener {
public void eventProcessed(XEvent e);
}
private Collectiondata
is the byte array directly from the x server and
* may be in little endian format.
* loadXSettings
. It is called from the System EDT
* if triggered by an XSETTINGS change.
*/
void parseXSettings(int screen_XXX_ignored,Map updatedSettings) {
if (updatedSettings == null || updatedSettings.isEmpty()) {
return;
}
Iterator i = updatedSettings.entrySet().iterator();
while (i.hasNext()) {
Map.Entry e = (Map.Entry)i.next();
String name = (String)e.getKey();
name = "gnome." + name;
setDesktopProperty(name, e.getValue());
log.fine("name = " + name + " value = " + e.getValue());
// XXX: we probably want to do something smarter. In
// particular, "Net" properties are of interest to the
// "core" AWT itself. E.g.
//
// Net/DndDragThreshold -> ???
// Net/DoubleClickTime -> awt.multiClickInterval
}
setDesktopProperty(SunToolkit.DESKTOPFONTHINTS,
SunToolkit.getDesktopFontHints());
Integer dragThreshold = null;
synchronized (this) {
dragThreshold = (Integer)desktopProperties.get("gnome.Net/DndDragThreshold");
}
if (dragThreshold != null) {
setDesktopProperty("DnD.gestureMotionThreshold", dragThreshold);
}
}
static int altMask;
static int metaMask;
static int numLockMask;
static int modeSwitchMask;
static int modLockIsShiftLock;
/* Like XKeysymToKeycode, but ensures that keysym is the primary
* symbol on the keycode returned. Returns zero otherwise.
*/
static int keysymToPrimaryKeycode(long sym) {
awtLock();
try {
int code = XlibWrapper.XKeysymToKeycode(getDisplay(), sym);
if (code == 0) {
return 0;
}
long primary = XlibWrapper.XKeycodeToKeysym(getDisplay(), code, 0);
if (sym != primary) {
return 0;
}
return code;
} finally {
awtUnlock();
}
}
static boolean getModifierState( int jkc ) {
int iKeyMask = 0;
long ks = XKeysym.javaKeycode2Keysym( jkc );
int kc = XlibWrapper.XKeysymToKeycode(getDisplay(), ks);
if (kc == 0) {
return false;
}
awtLock();
try {
XModifierKeymap modmap = new XModifierKeymap(
XlibWrapper.XGetModifierMapping(getDisplay()));
int nkeys = modmap.get_max_keypermod();
long map_ptr = modmap.get_modifiermap();
for( int k = 0; k < 8; k++ ) {
for (int i = 0; i < nkeys; ++i) {
int keycode = Native.getUByte(map_ptr, k * nkeys + i);
if (keycode == 0) {
continue; // ignore zero keycode
}
if (kc == keycode) {
iKeyMask = 1 << k;
break;
}
}
if( iKeyMask != 0 ) {
break;
}
}
XlibWrapper.XFreeModifiermap(modmap.pData);
if (iKeyMask == 0 ) {
return false;
}
// Now we know to which modifier is assigned the keycode
// correspondent to the keysym correspondent to the java
// keycode. We are going to check a state of this modifier.
// If a modifier is a weird one, we cannot help it.
long window = 0;
try{
// get any application window
window = ((Long)(winMap.firstKey())).longValue();
}catch(NoSuchElementException nex) {
// get root window
window = getDefaultRootWindow();
}
boolean res = XlibWrapper.XQueryPointer(getDisplay(), window,
XlibWrapper.larg1, //root
XlibWrapper.larg2, //child
XlibWrapper.larg3, //root_x
XlibWrapper.larg4, //root_y
XlibWrapper.larg5, //child_x
XlibWrapper.larg6, //child_y
XlibWrapper.larg7);//mask
int mask = Native.getInt(XlibWrapper.larg7);
return ((mask & iKeyMask) != 0);
} finally {
awtUnlock();
}
}
/* Assign meaning - alt, meta, etc. - to X modifiers mod1 ... mod5.
* Only consider primary symbols on keycodes attached to modifiers.
*/
static void setupModifierMap() {
final int metaL = keysymToPrimaryKeycode(XKeySymConstants.XK_Meta_L);
final int metaR = keysymToPrimaryKeycode(XKeySymConstants.XK_Meta_R);
final int altL = keysymToPrimaryKeycode(XKeySymConstants.XK_Alt_L);
final int altR = keysymToPrimaryKeycode(XKeySymConstants.XK_Alt_R);
final int numLock = keysymToPrimaryKeycode(XKeySymConstants.XK_Num_Lock);
final int modeSwitch = keysymToPrimaryKeycode(XKeySymConstants.XK_Mode_switch);
final int shiftLock = keysymToPrimaryKeycode(XKeySymConstants.XK_Shift_Lock);
final int capsLock = keysymToPrimaryKeycode(XKeySymConstants.XK_Caps_Lock);
final int modmask[] = { XConstants.ShiftMask, XConstants.LockMask, XConstants.ControlMask, XConstants.Mod1Mask,
XConstants.Mod2Mask, XConstants.Mod3Mask, XConstants.Mod4Mask, XConstants.Mod5Mask };
log.fine("In setupModifierMap");
awtLock();
try {
XModifierKeymap modmap = new XModifierKeymap(
XlibWrapper.XGetModifierMapping(getDisplay()));
int nkeys = modmap.get_max_keypermod();
long map_ptr = modmap.get_modifiermap();
for (int modn = XConstants.Mod1MapIndex;
modn <= XConstants.Mod5MapIndex;
++modn)
{
for (int i = 0; i < nkeys; ++i) {
/* for each keycode attached to this modifier */
int keycode = Native.getUByte(map_ptr, modn * nkeys + i);
if (keycode == 0) {
break;
}
if (metaMask == 0 &&
(keycode == metaL || keycode == metaR))
{
metaMask = modmask[modn];
break;
}
if (altMask == 0 && (keycode == altL || keycode == altR)) {
altMask = modmask[modn];
break;
}
if (numLockMask == 0 && keycode == numLock) {
numLockMask = modmask[modn];
break;
}
if (modeSwitchMask == 0 && keycode == modeSwitch) {
modeSwitchMask = modmask[modn];
break;
}
continue;
}
}
modLockIsShiftLock = 0;
for (int j = 0; j < nkeys; ++j) {
int keycode = Native.getUByte(map_ptr, XConstants.LockMapIndex * nkeys + j);
if (keycode == 0) {
break;
}
if (keycode == shiftLock) {
modLockIsShiftLock = 1;
break;
}
if (keycode == capsLock) {
break;
}
}
XlibWrapper.XFreeModifiermap(modmap.pData);
} finally {
awtUnlock();
}
if (log.isLoggable(PlatformLogger.FINE)) {
log.fine("metaMask = " + metaMask);
log.fine("altMask = " + altMask);
log.fine("numLockMask = " + numLockMask);
log.fine("modeSwitchMask = " + modeSwitchMask);
log.fine("modLockIsShiftLock = " + modLockIsShiftLock);
}
}
private static SortedMap timeoutTasks;
/**
* Removed the task from the list of waiting-to-be called tasks.
* If the task has been scheduled several times removes only first one.
*/
static void remove(Runnable task) {
if (task == null) {
throw new NullPointerException("task is null");
}
awtLock();
try {
if (timeoutTaskLog.isLoggable(PlatformLogger.FINER)) {
timeoutTaskLog.finer("Removing task " + task);
}
if (timeoutTasks == null) {
if (timeoutTaskLog.isLoggable(PlatformLogger.FINER)) {
timeoutTaskLog.finer("Task is not scheduled");
}
return;
}
Collection values = timeoutTasks.values();
Iterator iter = values.iterator();
while (iter.hasNext()) {
java.util.List list = (java.util.List)iter.next();
boolean removed = false;
if (list.contains(task)) {
list.remove(task);
if (list.isEmpty()) {
iter.remove();
}
break;
}
}
} finally {
awtUnlock();
}
}
static native void wakeup_poll();
/**
* Registers a Runnable which run()
method will be called
* once on the toolkit thread when a specified interval of time elapses.
*
* @param task a Runnable which run
method will be called
* on the toolkit thread when interval
milliseconds
* elapse
* @param interval an interal in milliseconds
*
* @throws NullPointerException if task
is null
* @throws IllegalArgumentException if interval
is not positive
*/
static void schedule(Runnable task, long interval) {
if (task == null) {
throw new NullPointerException("task is null");
}
if (interval <= 0) {
throw new IllegalArgumentException("interval " + interval + " is not positive");
}
awtLock();
try {
if (timeoutTaskLog.isLoggable(PlatformLogger.FINER)) {
timeoutTaskLog.finer("XToolkit.schedule(): current time={0}" +
"; interval={1}" +
"; task being added={2}" + "; tasks before addition={3}",
Long.valueOf(System.currentTimeMillis()), Long.valueOf(interval), task, timeoutTasks);
}
if (timeoutTasks == null) {
timeoutTasks = new TreeMap();
}
Long time = Long.valueOf(System.currentTimeMillis() + interval);
java.util.List tasks = (java.util.List)timeoutTasks.get(time);
if (tasks == null) {
tasks = new ArrayList(1);
timeoutTasks.put(time, tasks);
}
tasks.add(task);
if (timeoutTasks.get(timeoutTasks.firstKey()) == tasks && tasks.size() == 1) {
// Added task became first task - poll won't know
// about it so we need to wake it up
wakeup_poll();
}
} finally {
awtUnlock();
}
}
private long getNextTaskTime() {
awtLock();
try {
if (timeoutTasks == null || timeoutTasks.isEmpty()) {
return -1L;
}
return (Long)timeoutTasks.firstKey();
} finally {
awtUnlock();
}
}
/**
* Executes mature timeout tasks registered with schedule().
* Called from run() under awtLock.
*/
private static void callTimeoutTasks() {
if (timeoutTaskLog.isLoggable(PlatformLogger.FINER)) {
timeoutTaskLog.finer("XToolkit.callTimeoutTasks(): current time={0}" +
"; tasks={1}", Long.valueOf(System.currentTimeMillis()), timeoutTasks);
}
if (timeoutTasks == null || timeoutTasks.isEmpty()) {
return;
}
Long currentTime = Long.valueOf(System.currentTimeMillis());
Long time = (Long)timeoutTasks.firstKey();
while (time.compareTo(currentTime) <= 0) {
java.util.List tasks = (java.util.List)timeoutTasks.remove(time);
for (Iterator iter = tasks.iterator(); iter.hasNext();) {
Runnable task = (Runnable)iter.next();
if (timeoutTaskLog.isLoggable(PlatformLogger.FINER)) {
timeoutTaskLog.finer("XToolkit.callTimeoutTasks(): current time={0}" +
"; about to run task={1}", Long.valueOf(currentTime), task);
}
try {
task.run();
} catch (ThreadDeath td) {
throw td;
} catch (Throwable thr) {
processException(thr);
}
}
if (timeoutTasks.isEmpty()) {
break;
}
time = (Long)timeoutTasks.firstKey();
}
}
static long getAwtDefaultFg() {
return awt_defaultFg;
}
static boolean isLeftMouseButton(MouseEvent me) {
switch (me.getID()) {
case MouseEvent.MOUSE_PRESSED:
case MouseEvent.MOUSE_RELEASED:
return (me.getButton() == MouseEvent.BUTTON1);
case MouseEvent.MOUSE_ENTERED:
case MouseEvent.MOUSE_EXITED:
case MouseEvent.MOUSE_CLICKED:
case MouseEvent.MOUSE_DRAGGED:
return ((me.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != 0);
}
return false;
}
static boolean isRightMouseButton(MouseEvent me) {
int numButtons = ((Integer)getDefaultToolkit().getDesktopProperty("awt.mouse.numButtons")).intValue();
switch (me.getID()) {
case MouseEvent.MOUSE_PRESSED:
case MouseEvent.MOUSE_RELEASED:
return ((numButtons == 2 && me.getButton() == MouseEvent.BUTTON2) ||
(numButtons > 2 && me.getButton() == MouseEvent.BUTTON3));
case MouseEvent.MOUSE_ENTERED:
case MouseEvent.MOUSE_EXITED:
case MouseEvent.MOUSE_CLICKED:
case MouseEvent.MOUSE_DRAGGED:
return ((numButtons == 2 && (me.getModifiersEx() & InputEvent.BUTTON2_DOWN_MASK) != 0) ||
(numButtons > 2 && (me.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) != 0));
}
return false;
}
static long reset_time_utc;
static final long WRAP_TIME_MILLIS = 0x00000000FFFFFFFFL;
/*
* This function converts between the X server time (number of milliseconds
* since the last server reset) and the UTC time for the 'when' field of an
* InputEvent (or another event type with a timestamp).
*/
static long nowMillisUTC_offset(long server_offset) {
// ported from awt_util.c
/*
* Because Time is of type 'unsigned long', it is possible that Time will
* never wrap when using 64-bit Xlib. However, if a 64-bit client
* connects to a 32-bit server, I suspect the values will still wrap. So
* we should not attempt to remove the wrap checking even if _LP64 is
* true.
*/
long current_time_utc = System.currentTimeMillis();
if (log.isLoggable(PlatformLogger.FINER)) {
log.finer("reset_time=" + reset_time_utc + ", current_time=" + current_time_utc
+ ", server_offset=" + server_offset + ", wrap_time=" + WRAP_TIME_MILLIS);
}
if ((current_time_utc - reset_time_utc) > WRAP_TIME_MILLIS) {
reset_time_utc = System.currentTimeMillis() - getCurrentServerTime();
}
if (log.isLoggable(PlatformLogger.FINER)) {
log.finer("result = " + (reset_time_utc + server_offset));
}
return reset_time_utc + server_offset;
}
/**
* @see sun.awt.SunToolkit#needsXEmbedImpl
*/
protected boolean needsXEmbedImpl() {
// XToolkit implements supports for XEmbed-client protocol and
// requires the supports from the embedding host for it to work.
return true;
}
public boolean isModalityTypeSupported(Dialog.ModalityType modalityType) {
return (modalityType == null) ||
(modalityType == Dialog.ModalityType.MODELESS) ||
(modalityType == Dialog.ModalityType.DOCUMENT_MODAL) ||
(modalityType == Dialog.ModalityType.APPLICATION_MODAL) ||
(modalityType == Dialog.ModalityType.TOOLKIT_MODAL);
}
public boolean isModalExclusionTypeSupported(Dialog.ModalExclusionType exclusionType) {
return (exclusionType == null) ||
(exclusionType == Dialog.ModalExclusionType.NO_EXCLUDE) ||
(exclusionType == Dialog.ModalExclusionType.APPLICATION_EXCLUDE) ||
(exclusionType == Dialog.ModalExclusionType.TOOLKIT_EXCLUDE);
}
static EventQueue getEventQueue(Object target) {
AppContext appContext = targetToAppContext(target);
if (appContext != null) {
return (EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY);
}
return null;
}
static void removeSourceEvents(EventQueue queue,
Object source,
boolean removeAllEvents) {
AWTAccessor.getEventQueueAccessor()
.removeSourceEvents(queue, source, removeAllEvents);
}
public boolean isAlwaysOnTopSupported() {
for (XLayerProtocol proto : XWM.getWM().getProtocols(XLayerProtocol.class)) {
if (proto.supportsLayer(XLayerProtocol.LAYER_ALWAYS_ON_TOP)) {
return true;
}
}
return false;
}
public boolean useBufferPerWindow() {
return XToolkit.getBackingStoreType() == XConstants.NotUseful;
}
/**
* Returns one of XConstants: NotUseful, WhenMapped or Always.
* If backing store is not available on at least one screen, or
* java2d uses DGA(which conflicts with backing store) on at least one screen,
* or the string system property "sun.awt.backingStore" is neither "Always"
* nor "WhenMapped", then the method returns XConstants.NotUseful.
* Otherwise, if the system property "sun.awt.backingStore" is "WhenMapped",
* then the method returns XConstants.WhenMapped.
* Otherwise (i.e., if the system property "sun.awt.backingStore" is "Always"),
* the method returns XConstants.Always.
*/
static int getBackingStoreType() {
return backingStoreType;
}
private static void setBackingStoreType() {
String prop = (String)AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("sun.awt.backingStore"));
if (prop == null) {
backingStoreType = XConstants.NotUseful;
if (backingStoreLog.isLoggable(PlatformLogger.CONFIG)) {
backingStoreLog.config("The system property sun.awt.backingStore is not set" +
", by default backingStore=NotUseful");
}
return;
}
if (backingStoreLog.isLoggable(PlatformLogger.CONFIG)) {
backingStoreLog.config("The system property sun.awt.backingStore is " + prop);
}
prop = prop.toLowerCase();
if (prop.equals("always")) {
backingStoreType = XConstants.Always;
} else if (prop.equals("whenmapped")) {
backingStoreType = XConstants.WhenMapped;
} else {
backingStoreType = XConstants.NotUseful;
}
if (backingStoreLog.isLoggable(PlatformLogger.CONFIG)) {
backingStoreLog.config("backingStore(as provided by the system property)=" +
( backingStoreType == XConstants.NotUseful ? "NotUseful"
: backingStoreType == XConstants.WhenMapped ?
"WhenMapped" : "Always") );
}
if (sun.java2d.x11.X11SurfaceData.isDgaAvailable()) {
backingStoreType = XConstants.NotUseful;
if (backingStoreLog.isLoggable(PlatformLogger.CONFIG)) {
backingStoreLog.config("DGA is available, backingStore=NotUseful");
}
return;
}
awtLock();
try {
int screenCount = XlibWrapper.ScreenCount(getDisplay());
for (int i = 0; i < screenCount; i++) {
if (XlibWrapper.DoesBackingStore(XlibWrapper.ScreenOfDisplay(getDisplay(), i))
== XConstants.NotUseful) {
backingStoreType = XConstants.NotUseful;
if (backingStoreLog.isLoggable(PlatformLogger.CONFIG)) {
backingStoreLog.config("Backing store is not available on the screen " +
i + ", backingStore=NotUseful");
}
return;
}
}
} finally {
awtUnlock();
}
}
/**
* One of XConstants: NotUseful, WhenMapped or Always.
*/
private static int backingStoreType;
static final int XSUN_KP_BEHAVIOR = 1;
static final int XORG_KP_BEHAVIOR = 2;
static final int IS_SUN_KEYBOARD = 1;
static final int IS_NONSUN_KEYBOARD = 2;
static final int IS_KANA_KEYBOARD = 1;
static final int IS_NONKANA_KEYBOARD = 2;
static int awt_IsXsunKPBehavior = 0;
static boolean awt_UseXKB = false;
static boolean awt_UseXKB_Calls = false;
static int awt_XKBBaseEventCode = 0;
static int awt_XKBEffectiveGroup = 0; // so far, I don't use it leaving all calculations
// to XkbTranslateKeyCode
static long awt_XKBDescPtr = 0;
/**
* Check for Xsun convention regarding numpad keys.
* Xsun and some other servers (i.e. derived from Xsun)
* under certain conditions process numpad keys unlike Xorg.
*/
static boolean isXsunKPBehavior() {
awtLock();
try {
if( awt_IsXsunKPBehavior == 0 ) {
if( XlibWrapper.IsXsunKPBehavior(getDisplay()) ) {
awt_IsXsunKPBehavior = XSUN_KP_BEHAVIOR;
}else{
awt_IsXsunKPBehavior = XORG_KP_BEHAVIOR;
}
}
return awt_IsXsunKPBehavior == XSUN_KP_BEHAVIOR ? true : false;
} finally {
awtUnlock();
}
}
static int sunOrNotKeyboard = 0;
static int kanaOrNotKeyboard = 0;
static void resetKeyboardSniffer() {
sunOrNotKeyboard = 0;
kanaOrNotKeyboard = 0;
}
static boolean isSunKeyboard() {
if( sunOrNotKeyboard == 0 ) {
if( XlibWrapper.IsSunKeyboard( getDisplay() )) {
sunOrNotKeyboard = IS_SUN_KEYBOARD;
}else{
sunOrNotKeyboard = IS_NONSUN_KEYBOARD;
}
}
return (sunOrNotKeyboard == IS_SUN_KEYBOARD);
}
static boolean isKanaKeyboard() {
if( kanaOrNotKeyboard == 0 ) {
if( XlibWrapper.IsKanaKeyboard( getDisplay() )) {
kanaOrNotKeyboard = IS_KANA_KEYBOARD;
}else{
kanaOrNotKeyboard = IS_NONKANA_KEYBOARD;
}
}
return (kanaOrNotKeyboard == IS_KANA_KEYBOARD);
}
static boolean isXKBenabled() {
awtLock();
try {
return awt_UseXKB;
} finally {
awtUnlock();
}
}
/**
Query XKEYBOARD extension.
If possible, initialize xkb library.
*/
static boolean tryXKB() {
awtLock();
try {
String name = "XKEYBOARD";
// First, if there is extension at all.
awt_UseXKB = XlibWrapper.XQueryExtension( getDisplay(), name, XlibWrapper.larg1, XlibWrapper.larg2, XlibWrapper.larg3);
if( awt_UseXKB ) {
// There is a keyboard extension. Check if a client library is compatible.
// If not, don't use xkb calls.
// In this case we still may be Xkb-capable application.
awt_UseXKB_Calls = XlibWrapper.XkbLibraryVersion( XlibWrapper.larg1, XlibWrapper.larg2);
if( awt_UseXKB_Calls ) {
awt_UseXKB_Calls = XlibWrapper.XkbQueryExtension( getDisplay(), XlibWrapper.larg1, XlibWrapper.larg2,
XlibWrapper.larg3, XlibWrapper.larg4, XlibWrapper.larg5);
if( awt_UseXKB_Calls ) {
awt_XKBBaseEventCode = Native.getInt(XlibWrapper.larg2);
XlibWrapper.XkbSelectEvents (getDisplay(),
XConstants.XkbUseCoreKbd,
XConstants.XkbNewKeyboardNotifyMask |
XConstants.XkbMapNotifyMask ,//|
//XConstants.XkbStateNotifyMask,
XConstants.XkbNewKeyboardNotifyMask |
XConstants.XkbMapNotifyMask );//|
//XConstants.XkbStateNotifyMask);
XlibWrapper.XkbSelectEventDetails(getDisplay(), XConstants.XkbUseCoreKbd,
XConstants.XkbStateNotify,
XConstants.XkbGroupStateMask,
XConstants.XkbGroupStateMask);
//XXX ? XkbGroupLockMask last, XkbAllStateComponentsMask before last?
awt_XKBDescPtr = XlibWrapper.XkbGetMap(getDisplay(),
XConstants.XkbKeyTypesMask |
XConstants.XkbKeySymsMask |
XConstants.XkbModifierMapMask |
XConstants.XkbVirtualModsMask,
XConstants.XkbUseCoreKbd);
}
}
}
return awt_UseXKB;
} finally {
awtUnlock();
}
}
static boolean canUseXKBCalls() {
awtLock();
try {
return awt_UseXKB_Calls;
} finally {
awtUnlock();
}
}
static int getXKBEffectiveGroup() {
awtLock();
try {
return awt_XKBEffectiveGroup;
} finally {
awtUnlock();
}
}
static int getXKBBaseEventCode() {
awtLock();
try {
return awt_XKBBaseEventCode;
} finally {
awtUnlock();
}
}
static long getXKBKbdDesc() {
awtLock();
try {
return awt_XKBDescPtr;
} finally {
awtUnlock();
}
}
void freeXKB() {
awtLock();
try {
if (awt_UseXKB_Calls && awt_XKBDescPtr != 0) {
XlibWrapper.XkbFreeKeyboard(awt_XKBDescPtr, 0xFF, true);
awt_XKBDescPtr = 0;
}
} finally {
awtUnlock();
}
}
private void processXkbChanges(XEvent ev) {
// mapping change --> refresh kbd map
// state change --> get a new effective group; do I really need it
// or that should be left for XkbTranslateKeyCode?
XkbEvent xke = new XkbEvent( ev.getPData() );
int xkb_type = xke.get_any().get_xkb_type();
switch( xkb_type ) {
case XConstants.XkbNewKeyboardNotify :
if( awt_XKBDescPtr != 0 ) {
freeXKB();
}
awt_XKBDescPtr = XlibWrapper.XkbGetMap(getDisplay(),
XConstants.XkbKeyTypesMask |
XConstants.XkbKeySymsMask |
XConstants.XkbModifierMapMask |
XConstants.XkbVirtualModsMask,
XConstants.XkbUseCoreKbd);
//System.out.println("XkbNewKeyboard:"+(xke.get_new_kbd()));
break;
case XConstants.XkbMapNotify :
//TODO: provide a simple unit test.
XlibWrapper.XkbGetUpdatedMap(getDisplay(),
XConstants.XkbKeyTypesMask |
XConstants.XkbKeySymsMask |
XConstants.XkbModifierMapMask |
XConstants.XkbVirtualModsMask,
awt_XKBDescPtr);
//System.out.println("XkbMap:"+(xke.get_map()));
break;
case XConstants.XkbStateNotify :
// May use it later e.g. to obtain an effective group etc.
//System.out.println("XkbState:"+(xke.get_state()));
break;
default:
//System.out.println("XkbEvent of xkb_type "+xkb_type);
break;
}
}
private static long eventNumber;
public static long getEventNumber() {
awtLock();
try {
return eventNumber;
} finally {
awtUnlock();
}
}
private static XEventDispatcher oops_waiter;
private static boolean oops_updated;
private static boolean oops_failed;
private XAtom oops;
private static final long WORKAROUND_SLEEP = 100;
/**
* @inheritDoc
*/
protected boolean syncNativeQueue(final long timeout) {
XBaseWindow win = XBaseWindow.getXAWTRootWindow();
if (oops_waiter == null) {
oops_waiter = new XEventDispatcher() {
public void dispatchEvent(XEvent e) {
if (e.get_type() == XConstants.SelectionNotify) {
XSelectionEvent pe = e.get_xselection();
if (pe.get_property() == oops.getAtom()) {
oops_updated = true;
awtLockNotifyAll();
} else if (pe.get_selection() == XAtom.get("WM_S0").getAtom() &&
pe.get_target() == XAtom.get("VERSION").getAtom() &&
pe.get_property() == 0 &&
XlibWrapper.XGetSelectionOwner(getDisplay(), XAtom.get("WM_S0").getAtom()) == 0)
{
// WM forgot to acquire selection or there is no WM
oops_failed = true;
awtLockNotifyAll();
}
}
}
};
}
if (oops == null) {
oops = XAtom.get("OOPS");
}
awtLock();
try {
addEventDispatcher(win.getWindow(), oops_waiter);
oops_updated = false;
oops_failed = false;
// Wait for selection notify for oops on win
long event_number = getEventNumber();
XAtom atom = XAtom.get("WM_S0");
eventLog.finer("WM_S0 selection owner {0}", XlibWrapper.XGetSelectionOwner(getDisplay(), atom.getAtom()));
XlibWrapper.XConvertSelection(getDisplay(), atom.getAtom(),
XAtom.get("VERSION").getAtom(), oops.getAtom(),
win.getWindow(), XConstants.CurrentTime);
XSync();
eventLog.finer("Requested OOPS");
long start = System.currentTimeMillis();
while (!oops_updated && !oops_failed) {
try {
awtLockWait(timeout);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
// This "while" is a protection from spurious
// wake-ups. However, we shouldn't wait for too long
if ((System.currentTimeMillis() - start > timeout) && timeout >= 0) {
throw new OperationTimedOut(Long.toString(System.currentTimeMillis() - start));
}
}
if (oops_failed && getEventNumber() - event_number == 1) {
// If selection update failed we can simply wait some time
// hoping some events will arrive
awtUnlock();
eventLog.finest("Emergency sleep");
try {
Thread.sleep(WORKAROUND_SLEEP);
} catch (InterruptedException ie) {
throw new RuntimeException(ie);
} finally {
awtLock();
}
}
return getEventNumber() - event_number > 2;
} finally {
removeEventDispatcher(win.getWindow(), oops_waiter);
eventLog.finer("Exiting syncNativeQueue");
awtUnlock();
}
}
public void grab(Window w) {
if (w.getPeer() != null) {
((XWindowPeer)w.getPeer()).setGrab(true);
}
}
public void ungrab(Window w) {
if (w.getPeer() != null) {
((XWindowPeer)w.getPeer()).setGrab(false);
}
}
/**
* Returns if the java.awt.Desktop class is supported on the current
* desktop.
*