1098 } 1099 } 1100 }else { 1101 // No input method instance found. For example, there's a Java Input Method. 1102 // Produce do-it-yourself keysym and perhaps unicode character. 1103 keysym[0] = xkeycodeToKeysym(ev); 1104 unicodeKey = keysymToUnicode( keysym[0], ev.get_state() ); 1105 if (keyEventLog.isLoggable(PlatformLogger.FINE)) { 1106 keyEventLog.fine("--XWindow.java XIM is absent; hex keysym:"+Long.toHexString(keysym[0])+"\n"+ 1107 " unicode key:"+Integer.toHexString((int)unicodeKey)); 1108 } 1109 } 1110 // Keysym should be converted to Unicode, if possible and necessary, 1111 // and Java KeyEvent keycode should be calculated. 1112 // For press we should post pressed & typed Java events. 1113 // 1114 // Press event might be not processed to this time because 1115 // (1) either XIM could not handle it or 1116 // (2) it was Latin 1:1 mapping. 1117 // 1118 XKeysym.Keysym2JavaKeycode jkc = XKeysym.getJavaKeycode(ev); 1119 if( jkc == null ) { 1120 jkc = new XKeysym.Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDEFINED, java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN); 1121 } 1122 1123 // Take the first keysym from a keysym array associated with the XKeyevent 1124 // and convert it to Unicode. Then, even if a Java keycode for the keystroke 1125 // is undefined, we still have a guess of what has been engraved on a keytop. 1126 int unicodeFromPrimaryKeysym = keysymToUnicode( xkeycodeToPrimaryKeysym(ev) ,0); 1127 1128 if (keyEventLog.isLoggable(PlatformLogger.FINE)) { 1129 keyEventLog.fine(">>>Fire Event:"+ 1130 (ev.get_type() == XConstants.KeyPress ? "KEY_PRESSED; " : "KEY_RELEASED; ")+ 1131 "jkeycode:decimal="+jkc.getJavaKeycode()+ 1132 ", hex=0x"+Integer.toHexString(jkc.getJavaKeycode())+"; "+ 1133 " legacy jkeycode: decimal="+XKeysym.getLegacyJavaKeycodeOnly(ev)+ 1134 ", hex=0x"+Integer.toHexString(XKeysym.getLegacyJavaKeycodeOnly(ev))+"; " 1135 ); 1136 } 1137 1138 int jkeyToReturn = XKeysym.getLegacyJavaKeycodeOnly(ev); // someway backward compatible 1139 int jkeyExtended = jkc.getJavaKeycode() == java.awt.event.KeyEvent.VK_UNDEFINED ? 1140 primaryUnicode2JavaKeycode( unicodeFromPrimaryKeysym ) : 1141 jkc.getJavaKeycode(); 1142 postKeyEvent( java.awt.event.KeyEvent.KEY_PRESSED, 1143 ev.get_time(), 1144 jkeyToReturn, 1145 (unicodeKey == 0 ? java.awt.event.KeyEvent.CHAR_UNDEFINED : unicodeKey), 1146 jkc.getKeyLocation(), 1147 ev.get_state(),ev.getPData(), XKeyEvent.getSize(), (long)(ev.get_keycode()), 1148 unicodeFromPrimaryKeysym, 1149 jkeyExtended); 1150 1151 1152 if( unicodeKey > 0 ) { 1153 keyEventLog.fine("fire _TYPED on "+unicodeKey); 1154 postKeyEvent( java.awt.event.KeyEvent.KEY_TYPED, 1155 ev.get_time(), 1156 java.awt.event.KeyEvent.VK_UNDEFINED, 1157 unicodeKey, 1158 java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN, 1159 ev.get_state(),ev.getPData(), XKeyEvent.getSize(), (long)0, 1160 unicodeFromPrimaryKeysym, 1161 java.awt.event.KeyEvent.VK_UNDEFINED); 1162 1163 } 1164 1165 1166 } 1167 1168 public void handleKeyRelease(XEvent xev) { 1169 super.handleKeyRelease(xev); 1170 XKeyEvent ev = xev.get_xkey(); 1171 if (eventLog.isLoggable(PlatformLogger.FINE)) eventLog.fine(ev.toString()); 1172 if (isEventDisabled(xev)) { 1173 return; 1174 } 1175 handleKeyRelease(ev); 1176 } 1177 // un-private it if you need to call it from elsewhere 1178 private void handleKeyRelease(XKeyEvent ev) { 1179 long keysym[] = new long[2]; 1180 int unicodeKey = 0; 1181 keysym[0] = XConstants.NoSymbol; 1182 1183 if (keyEventLog.isLoggable(PlatformLogger.FINE)) { 1184 logIncomingKeyEvent( ev ); 1185 } 1186 // Keysym should be converted to Unicode, if possible and necessary, 1187 // and Java KeyEvent keycode should be calculated. 1188 // For release we should post released event. 1189 // 1190 XKeysym.Keysym2JavaKeycode jkc = XKeysym.getJavaKeycode(ev); 1191 if( jkc == null ) { 1192 jkc = new XKeysym.Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDEFINED, java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN); 1193 } 1194 if (keyEventLog.isLoggable(PlatformLogger.FINE)) { 1195 keyEventLog.fine(">>>Fire Event:"+ 1196 (ev.get_type() == XConstants.KeyPress ? "KEY_PRESSED; " : "KEY_RELEASED; ")+ 1197 "jkeycode:decimal="+jkc.getJavaKeycode()+ 1198 ", hex=0x"+Integer.toHexString(jkc.getJavaKeycode())+"; "+ 1199 " legacy jkeycode: decimal="+XKeysym.getLegacyJavaKeycodeOnly(ev)+ 1200 ", hex=0x"+Integer.toHexString(XKeysym.getLegacyJavaKeycodeOnly(ev))+"; " 1201 ); 1202 } 1203 // We obtain keysym from IM and derive unicodeKey from it for KeyPress only. 1204 // We used to cache that value and retrieve it on KeyRelease, 1205 // but in case for example of a dead key+vowel pair, a vowel after a deadkey 1206 // might never be cached before. 1207 // Also, switching between keyboard layouts, we might cache a wrong letter. 1208 // That's why we use the same procedure as if there was no IM instance: do-it-yourself unicode. 1209 unicodeKey = keysymToUnicode( xkeycodeToKeysym(ev), ev.get_state() ); 1210 1211 // Take a first keysym from a keysym array associated with the XKeyevent 1212 // and convert it to Unicode. Then, even if Java keycode for the keystroke 1213 // is undefined, we still will have a guess of what was engraved on a keytop. 1214 int unicodeFromPrimaryKeysym = keysymToUnicode( xkeycodeToPrimaryKeysym(ev) ,0); 1215 1216 int jkeyToReturn = XKeysym.getLegacyJavaKeycodeOnly(ev); // someway backward compatible 1217 int jkeyExtended = jkc.getJavaKeycode() == java.awt.event.KeyEvent.VK_UNDEFINED ? 1218 primaryUnicode2JavaKeycode( unicodeFromPrimaryKeysym ) : 1219 jkc.getJavaKeycode(); 1220 postKeyEvent( java.awt.event.KeyEvent.KEY_RELEASED, 1221 ev.get_time(), 1222 jkeyToReturn, 1223 (unicodeKey == 0 ? java.awt.event.KeyEvent.CHAR_UNDEFINED : unicodeKey), 1224 jkc.getKeyLocation(), 1225 ev.get_state(),ev.getPData(), XKeyEvent.getSize(), (long)(ev.get_keycode()), 1226 unicodeFromPrimaryKeysym, 1227 jkeyExtended); 1228 1229 1230 } 1231 1232 /* 1233 * XmNiconic and Map/UnmapNotify (that XmNiconic relies on) are 1234 * unreliable, since mapping changes can happen for a virtual desktop 1235 * switch or MacOS style shading that became quite popular under X as 1236 * well. Yes, it probably should not be this way, as it violates 1237 * ICCCM, but reality is that quite a lot of window managers abuse 1238 * mapping state. 1239 */ 1240 int getWMState() { 1241 if (stateChanged) { 1242 stateChanged = false; 1243 WindowPropertyGetter getter = 1244 new WindowPropertyGetter(window, XWM.XA_WM_STATE, 0, 1, false, 1245 XWM.XA_WM_STATE); 1246 try { 1247 int status = getter.execute(); 1248 if (status != XConstants.Success || getter.getData() == 0) { 1249 return savedState = XUtilConstants.WithdrawnState; 1250 } | 1098 } 1099 } 1100 }else { 1101 // No input method instance found. For example, there's a Java Input Method. 1102 // Produce do-it-yourself keysym and perhaps unicode character. 1103 keysym[0] = xkeycodeToKeysym(ev); 1104 unicodeKey = keysymToUnicode( keysym[0], ev.get_state() ); 1105 if (keyEventLog.isLoggable(PlatformLogger.FINE)) { 1106 keyEventLog.fine("--XWindow.java XIM is absent; hex keysym:"+Long.toHexString(keysym[0])+"\n"+ 1107 " unicode key:"+Integer.toHexString((int)unicodeKey)); 1108 } 1109 } 1110 // Keysym should be converted to Unicode, if possible and necessary, 1111 // and Java KeyEvent keycode should be calculated. 1112 // For press we should post pressed & typed Java events. 1113 // 1114 // Press event might be not processed to this time because 1115 // (1) either XIM could not handle it or 1116 // (2) it was Latin 1:1 mapping. 1117 // 1118 // Preserve modifiers to get Java key code for dead keys 1119 boolean isDeadKey = isDeadKey(keysym[0]); 1120 XKeysym.Keysym2JavaKeycode jkc = isDeadKey ? XKeysym.getJavaKeycode(keysym[0]) 1121 : XKeysym.getJavaKeycode(ev); 1122 if( jkc == null ) { 1123 jkc = new XKeysym.Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDEFINED, java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN); 1124 } 1125 1126 // Take the first keysym from a keysym array associated with the XKeyevent 1127 // and convert it to Unicode. Then, even if a Java keycode for the keystroke 1128 // is undefined, we still have a guess of what has been engraved on a keytop. 1129 int unicodeFromPrimaryKeysym = keysymToUnicode( xkeycodeToPrimaryKeysym(ev) ,0); 1130 1131 if (keyEventLog.isLoggable(PlatformLogger.FINE)) { 1132 keyEventLog.fine(">>>Fire Event:"+ 1133 (ev.get_type() == XConstants.KeyPress ? "KEY_PRESSED; " : "KEY_RELEASED; ")+ 1134 "jkeycode:decimal="+jkc.getJavaKeycode()+ 1135 ", hex=0x"+Integer.toHexString(jkc.getJavaKeycode())+"; "+ 1136 " legacy jkeycode: decimal="+XKeysym.getLegacyJavaKeycodeOnly(ev)+ 1137 ", hex=0x"+Integer.toHexString(XKeysym.getLegacyJavaKeycodeOnly(ev))+"; " 1138 ); 1139 } 1140 1141 int jkeyToReturn = XKeysym.getLegacyJavaKeycodeOnly(ev); // someway backward compatible 1142 int jkeyExtended = jkc.getJavaKeycode() == java.awt.event.KeyEvent.VK_UNDEFINED ? 1143 primaryUnicode2JavaKeycode( unicodeFromPrimaryKeysym ) : 1144 jkc.getJavaKeycode(); 1145 postKeyEvent( java.awt.event.KeyEvent.KEY_PRESSED, 1146 ev.get_time(), 1147 isDeadKey ? jkeyExtended : jkeyToReturn, 1148 (unicodeKey == 0 ? java.awt.event.KeyEvent.CHAR_UNDEFINED : unicodeKey), 1149 jkc.getKeyLocation(), 1150 ev.get_state(),ev.getPData(), XKeyEvent.getSize(), (long)(ev.get_keycode()), 1151 unicodeFromPrimaryKeysym, 1152 jkeyExtended); 1153 1154 1155 if (unicodeKey > 0 && !isDeadKey) { 1156 keyEventLog.fine("fire _TYPED on "+unicodeKey); 1157 postKeyEvent( java.awt.event.KeyEvent.KEY_TYPED, 1158 ev.get_time(), 1159 java.awt.event.KeyEvent.VK_UNDEFINED, 1160 unicodeKey, 1161 java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN, 1162 ev.get_state(),ev.getPData(), XKeyEvent.getSize(), (long)0, 1163 unicodeFromPrimaryKeysym, 1164 java.awt.event.KeyEvent.VK_UNDEFINED); 1165 1166 } 1167 1168 1169 } 1170 1171 public void handleKeyRelease(XEvent xev) { 1172 super.handleKeyRelease(xev); 1173 XKeyEvent ev = xev.get_xkey(); 1174 if (eventLog.isLoggable(PlatformLogger.FINE)) eventLog.fine(ev.toString()); 1175 if (isEventDisabled(xev)) { 1176 return; 1177 } 1178 handleKeyRelease(ev); 1179 } 1180 // un-private it if you need to call it from elsewhere 1181 private void handleKeyRelease(XKeyEvent ev) { 1182 int unicodeKey = 0; 1183 1184 if (keyEventLog.isLoggable(PlatformLogger.FINE)) { 1185 logIncomingKeyEvent( ev ); 1186 } 1187 // Keysym should be converted to Unicode, if possible and necessary, 1188 // and Java KeyEvent keycode should be calculated. 1189 // For release we should post released event. 1190 // 1191 // Preserve modifiers to get Java key code for dead keys 1192 long keysym = xkeycodeToKeysym(ev); 1193 boolean isDeadKey = isDeadKey(keysym); 1194 XKeysym.Keysym2JavaKeycode jkc = isDeadKey ? XKeysym.getJavaKeycode(keysym) 1195 : XKeysym.getJavaKeycode(ev); 1196 if( jkc == null ) { 1197 jkc = new XKeysym.Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDEFINED, java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN); 1198 } 1199 if (keyEventLog.isLoggable(PlatformLogger.FINE)) { 1200 keyEventLog.fine(">>>Fire Event:"+ 1201 (ev.get_type() == XConstants.KeyPress ? "KEY_PRESSED; " : "KEY_RELEASED; ")+ 1202 "jkeycode:decimal="+jkc.getJavaKeycode()+ 1203 ", hex=0x"+Integer.toHexString(jkc.getJavaKeycode())+"; "+ 1204 " legacy jkeycode: decimal="+XKeysym.getLegacyJavaKeycodeOnly(ev)+ 1205 ", hex=0x"+Integer.toHexString(XKeysym.getLegacyJavaKeycodeOnly(ev))+"; " 1206 ); 1207 } 1208 // We obtain keysym from IM and derive unicodeKey from it for KeyPress only. 1209 // We used to cache that value and retrieve it on KeyRelease, 1210 // but in case for example of a dead key+vowel pair, a vowel after a deadkey 1211 // might never be cached before. 1212 // Also, switching between keyboard layouts, we might cache a wrong letter. 1213 // That's why we use the same procedure as if there was no IM instance: do-it-yourself unicode. 1214 unicodeKey = keysymToUnicode( xkeycodeToKeysym(ev), ev.get_state() ); 1215 1216 // Take a first keysym from a keysym array associated with the XKeyevent 1217 // and convert it to Unicode. Then, even if Java keycode for the keystroke 1218 // is undefined, we still will have a guess of what was engraved on a keytop. 1219 int unicodeFromPrimaryKeysym = keysymToUnicode( xkeycodeToPrimaryKeysym(ev) ,0); 1220 1221 int jkeyToReturn = XKeysym.getLegacyJavaKeycodeOnly(ev); // someway backward compatible 1222 int jkeyExtended = jkc.getJavaKeycode() == java.awt.event.KeyEvent.VK_UNDEFINED ? 1223 primaryUnicode2JavaKeycode( unicodeFromPrimaryKeysym ) : 1224 jkc.getJavaKeycode(); 1225 postKeyEvent( java.awt.event.KeyEvent.KEY_RELEASED, 1226 ev.get_time(), 1227 isDeadKey ? jkeyExtended : jkeyToReturn, 1228 (unicodeKey == 0 ? java.awt.event.KeyEvent.CHAR_UNDEFINED : unicodeKey), 1229 jkc.getKeyLocation(), 1230 ev.get_state(),ev.getPData(), XKeyEvent.getSize(), (long)(ev.get_keycode()), 1231 unicodeFromPrimaryKeysym, 1232 jkeyExtended); 1233 1234 1235 } 1236 1237 1238 private boolean isDeadKey(long keysym){ 1239 return XKeySymConstants.XK_dead_grave <= keysym && keysym <= XKeySymConstants.XK_dead_semivoiced_sound; 1240 } 1241 1242 /* 1243 * XmNiconic and Map/UnmapNotify (that XmNiconic relies on) are 1244 * unreliable, since mapping changes can happen for a virtual desktop 1245 * switch or MacOS style shading that became quite popular under X as 1246 * well. Yes, it probably should not be this way, as it violates 1247 * ICCCM, but reality is that quite a lot of window managers abuse 1248 * mapping state. 1249 */ 1250 int getWMState() { 1251 if (stateChanged) { 1252 stateChanged = false; 1253 WindowPropertyGetter getter = 1254 new WindowPropertyGetter(window, XWM.XA_WM_STATE, 0, 1, false, 1255 XWM.XA_WM_STATE); 1256 try { 1257 int status = getter.execute(); 1258 if (status != XConstants.Success || getter.getData() == 0) { 1259 return savedState = XUtilConstants.WithdrawnState; 1260 } |