< prev index next >
src/solaris/classes/sun/awt/X11/XToolkit.java
Print this page
rev 1565 : 5100701: Toolkit.getLockingKeyState() does not work on XToolkit, but works on Motif
Summary: Does not work on Motif but works on XToolkit now; implemented using XQueryPointer.
Reviewed-by: anthony
rev 1566 : 6680988: KeyEvent is still missing VK values for many keyboards
Summary: 2 new methods and some fields added to KeyEvent, plus hash of constants introduced
Reviewed-by: art
rev 1568 : 6711676: Numpad keys trigger more than one KeyEvent.
Summary: Introduce a new sniffer based on server keymap.
Reviewed-by: art
rev 1569 : 5099725: AWT doesn't seem to handle MappingNotify events under X11.
5036807: Pressing action keys "STOP/AGAIN/COMPOSE" generates keycode of F11/F12 keys.
4787377: VK_STOP key on Solaris generates wrong Key Code
Summary: Added an event processing lumped with similar native code for similar bugs.
Reviewed-by: art
rev 1571 : 8010297: Missing isLoggable() checks in logging code
Summary: Add isLoggable() checks
Reviewed-by: anthony, mchung, serb
Contributed-by: Laurent Bourges <bourges.laurent@gmail.com>
*** 184,195 ****
--- 184,197 ----
return current_error_handler.handleError(display, event);
} else {
return SAVED_ERROR_HANDLER(display, event);
}
} catch (Throwable z) {
+ if (log.isLoggable(Level.FINE)) {
log.log(Level.FINE, "Error in GlobalErrorHandler", z);
}
+ }
return 0;
}
//---- END OF ERROR HANDLER CODE ----//
*** 275,286 ****
--- 277,291 ----
void init() {
awtLock();
try {
XlibWrapper.XSupportsLocale();
if (XlibWrapper.XSetLocaleModifiers("") == null) {
+ if (log.isLoggable(Level.FINER)) {
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(),
*** 289,303 ****
saved_error_handler = XlibWrapper.SetToolkitErrorHandler();
} finally {
awtUnlock();
}
- if (log.isLoggable(Level.FINE)) {
PrivilegedAction<Void> a = new PrivilegedAction<Void>() {
public Void run() {
Thread shutdownThread = new Thread(ThreadGroupUtils.getRootThreadGroup(), "XToolkt-Shutdown-Thread") {
public void run() {
if (log.isLoggable(Level.FINE)) {
dumpPeers();
}
}
};
--- 294,308 ----
saved_error_handler = XlibWrapper.SetToolkitErrorHandler();
} finally {
awtUnlock();
}
PrivilegedAction<Void> a = new PrivilegedAction<Void>() {
public Void run() {
Thread shutdownThread = new Thread(ThreadGroupUtils.getRootThreadGroup(), "XToolkt-Shutdown-Thread") {
public void run() {
+ freeXKB();
if (log.isLoggable(Level.FINE)) {
dumpPeers();
}
}
};
*** 306,316 ****
return null;
}
};
AccessController.doPrivileged(a);
}
- }
static String getCorrectXIDString(String val) {
if (val != null) {
return val.replace('.', '-');
} else {
--- 311,320 ----
*** 511,520 ****
--- 515,534 ----
(ev.get_type() == MotionNotify || ev.get_type() == EnterNotify || ev.get_type() == LeaveNotify))
{
processGlobalMotionEvent(ev);
}
+ if( ev.get_type() == XConstants.MappingNotify ) {
+ // The 'window' field in this event is unused.
+ // This application itself does nothing to initiate such an event
+ // (no calls of XChangeKeyboardMapping etc.).
+ // SunRay server sends this event to the application once on every
+ // keyboard (not just layout) change which means, quite seldom.
+ XlibWrapper.XRefreshKeyboardMapping(ev.pData);
+ resetKeyboardSniffer();
+ setupModifierMap();
+ }
XBaseWindow.dispatchToWindow(ev);
Collection dispatchers = null;
synchronized(winToDispatcher) {
Long key = Long.valueOf(xany.get_window());
*** 574,583 ****
--- 588,600 ----
}
if (ev.get_type() != NoExpose) {
eventNumber++;
}
+ if (awt_UseXKB_Calls && ev.get_type() == awt_XKBBaseEventCode) {
+ processXkbChanges(ev);
+ }
if (XDropTargetEventProcessor.processEvent(ev) ||
XDragSourceContextPeer.processEvent(ev)) {
continue;
}
*** 1090,1099 ****
--- 1107,1129 ----
}
public Map mapInputMethodHighlight(InputMethodHighlight highlight) {
return XInputMethod.mapInputMethodHighlight(highlight);
}
+ @Override
+ public boolean getLockingKeyState(int key) {
+ if (! (key == KeyEvent.VK_CAPS_LOCK || key == KeyEvent.VK_NUM_LOCK ||
+ key == KeyEvent.VK_SCROLL_LOCK || key == KeyEvent.VK_KANA_LOCK)) {
+ throw new IllegalArgumentException("invalid key for Toolkit.getLockingKeyState");
+ }
+ awtLock();
+ try {
+ return getModifierState( key );
+ } finally {
+ awtUnlock();
+ }
+ }
public Clipboard getSystemClipboard() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkSystemClipboardAccess();
*** 1366,1376 ****
awtLockWait();
}
}
} catch (InterruptedException ie) {
// Note: the returned timeStamp can be incorrect in this case.
! if (log.isLoggable(Level.FINE)) log.fine("Catched exception, timeStamp may not be correct (ie = " + ie + ")");
}
} finally {
awtUnlock();
}
return timeStamp;
--- 1396,1408 ----
awtLockWait();
}
}
} catch (InterruptedException ie) {
// Note: the returned timeStamp can be incorrect in this case.
! if (log.isLoggable(Level.FINE)) {
! log.fine("Catched exception, timeStamp may not be correct (ie = " + ie + ")");
! }
}
} finally {
awtUnlock();
}
return timeStamp;
*** 1495,1505 ****
--- 1527,1539 ----
Map.Entry e = (Map.Entry)i.next();
String name = (String)e.getKey();
name = "gnome." + name;
setDesktopProperty(name, e.getValue());
+ if (log.isLoggable(Level.FINE)) {
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.
//
*** 1545,1554 ****
--- 1579,1648 ----
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() {
*** 1988,2047 ****
/**
* One of XConstants: NotUseful, WhenMapped or Always.
*/
private static int backingStoreType;
! static boolean awt_ServerInquired = false;
! static boolean awt_IsXsunServer = false;
! static boolean awt_XKBInquired = false;
static boolean awt_UseXKB = false;
/**
! Try to understand if it is Xsun server.
! By now (2005) Sun is vendor of Xsun and Xorg servers; we only return true if Xsun is running.
*/
! static boolean isXsunServer() {
awtLock();
try {
! if( awt_ServerInquired ) {
! return awt_IsXsunServer;
}
- if( ! XlibWrapper.ServerVendor(getDisplay()).startsWith("Sun Microsystems") ) {
- awt_ServerInquired = true;
- awt_IsXsunServer = false;
- return false;
}
! // Now, it's Sun. It still may be Xorg though, eg on Solaris 10, x86.
! // Today (2005), VendorRelease of Xorg is a Big Number unlike Xsun.
! if( XlibWrapper.VendorRelease(getDisplay()) > 10000 ) {
! awt_ServerInquired = true;
! awt_IsXsunServer = false;
! return false;
}
! awt_ServerInquired = true;
! awt_IsXsunServer = true;
! return true;
} finally {
awtUnlock();
}
}
/**
Query XKEYBOARD extension.
*/
! static boolean isXKBenabled() {
awtLock();
try {
- if( awt_XKBInquired ) {
- return awt_UseXKB;
- }
- awt_XKBInquired = true;
String name = "XKEYBOARD";
awt_UseXKB = XlibWrapper.XQueryExtension( getDisplay(), name, XlibWrapper.larg1, XlibWrapper.larg2, XlibWrapper.larg3);
return awt_UseXKB;
} finally {
awtUnlock();
}
}
private static long eventNumber;
public static long getEventNumber() {
awtLock();
try {
--- 2082,2291 ----
/**
* 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);
+ }
+ } 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 {
*** 2097,2107 ****
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.log(Level.FINER, "WM_S0 selection owner {0}", new Object[] {XlibWrapper.XGetSelectionOwner(getDisplay(), atom.getAtom())});
XlibWrapper.XConvertSelection(getDisplay(), atom.getAtom(),
XAtom.get("VERSION").getAtom(), oops.getAtom(),
win.getWindow(), XlibWrapper.CurrentTime);
XSync();
--- 2341,2354 ----
oops_updated = false;
oops_failed = false;
// Wait for selection notify for oops on win
long event_number = getEventNumber();
XAtom atom = XAtom.get("WM_S0");
! if (eventLog.isLoggable(Level.FINER)) {
! eventLog.log(Level.FINER, "WM_S0 selection owner {0}",
! new Object[] {XlibWrapper.XGetSelectionOwner(getDisplay(), atom.getAtom())});
! }
XlibWrapper.XConvertSelection(getDisplay(), atom.getAtom(),
XAtom.get("VERSION").getAtom(), oops.getAtom(),
win.getWindow(), XlibWrapper.CurrentTime);
XSync();
*** 2123,2133 ****
--- 2370,2382 ----
}
if (oops_failed && getEventNumber() - event_number == 1) {
// If selection update failed we can simply wait some time
// hoping some events will arrive
awtUnlock();
+ if (eventLog.isLoggable(Level.FINEST)) {
eventLog.log(Level.FINEST, "Emergency sleep");
+ }
try {
Thread.sleep(WORKAROUND_SLEEP);
} catch (InterruptedException ie) {
throw new RuntimeException(ie);
} finally {
*** 2135,2145 ****
--- 2384,2396 ----
}
}
return getEventNumber() - event_number > 2;
} finally {
removeEventDispatcher(win.getWindow(), oops_waiter);
+ if (eventLog.isLoggable(Level.FINER)) {
eventLog.log(Level.FINER, "Exiting syncNativeQueue");
+ }
awtUnlock();
}
}
public void grab(Window w) {
if (w.getPeer() != null) {
< prev index next >