< 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 >