< prev index next >

src/solaris/classes/sun/awt/X11/XWindow.java

Print this page
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 1570 : 8000626: Implement dead key detection for KeyEvent on Linux
Reviewed-by: kizune
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>
   1 /*
   2  * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 370 
 371     public Rectangle getTargetBounds() {
 372         return target.getBounds();
 373     }
 374 
 375     /**
 376      * Returns true if the event has been handled and should not be
 377      * posted to Java.
 378      */
 379     boolean prePostEvent(AWTEvent e) {
 380         return false;
 381     }
 382 
 383     static void sendEvent(final AWTEvent e) {
 384         PeerEvent pe = new PeerEvent(Toolkit.getDefaultToolkit(), new Runnable() {
 385                 public void run() {
 386                     AWTAccessor.getAWTEventAccessor().setPosted(e);
 387                     ((Component)e.getSource()).dispatchEvent(e);
 388                 }
 389             }, PeerEvent.ULTIMATE_PRIORITY_EVENT);
 390         if (focusLog.isLoggable(Level.FINER) && (e instanceof FocusEvent)) focusLog.finer("Sending " + e);


 391         XToolkit.postEvent(XToolkit.targetToAppContext(e.getSource()), pe);
 392     }
 393 
 394 
 395 /*
 396  * Post an event to the event queue.
 397  */
 398 // NOTE: This method may be called by privileged threads.
 399 //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
 400     void postEvent(AWTEvent event) {
 401         XToolkit.postEvent(XToolkit.targetToAppContext(event.getSource()), event);
 402     }
 403 
 404     static void postEventStatic(AWTEvent event) {
 405         XToolkit.postEvent(XToolkit.targetToAppContext(event.getSource()), event);
 406     }
 407 
 408     public void postEventToEventQueue(final AWTEvent event) {
 409         //fix for 6239938 : Choice drop-down does not disappear when it loses focus, on XToolkit
 410         if (!prePostEvent(event)) {


 614                 rbutton = XlibWrapper.XGetPointerMapping(XToolkit.getDisplay(), XlibWrapper.ibuffer, 3);
 615             }
 616             finally {
 617                 XToolkit.awtUnlock();
 618             }
 619         }
 620         return rbutton;
 621     }
 622 
 623     static int getMouseMovementSmudge() {
 624         //TODO: It's possible to read corresponding settings
 625         return AWT_MULTICLICK_SMUDGE;
 626     }
 627 
 628     public void handleButtonPressRelease(XEvent xev) {
 629         super.handleButtonPressRelease(xev);
 630         XButtonEvent xbe = xev.get_xbutton();
 631         if (isEventDisabled(xev)) {
 632             return;
 633         }
 634         if (eventLog.isLoggable(Level.FINE)) eventLog.fine(xbe.toString());


 635         long when;
 636         int modifiers;
 637         boolean popupTrigger = false;
 638         int button=0;
 639         boolean wheel_mouse = false;
 640         long lbutton = xbe.get_button();
 641         int type = xev.get_type();
 642         when = xbe.get_time();
 643         long jWhen = XToolkit.nowMillisUTC_offset(when);
 644 
 645         int x = xbe.get_x();
 646         int y = xbe.get_y();
 647         if (xev.get_xany().get_window() != window) {
 648             Point localXY = toLocal(xbe.get_x_root(), xbe.get_y_root());
 649             x = localXY.x;
 650             y = localXY.y;
 651         }
 652 
 653         if (type == XlibWrapper.ButtonPress) {
 654             XWindow lastWindow = (lastWindowRef != null) ? ((XWindow)lastWindowRef.get()):(null);
 655             /*
 656                multiclick checking
 657             */
 658             if (eventLog.isLoggable(Level.FINEST)) eventLog.finest("lastWindow = " + lastWindow + ", lastButton "

 659                                                                    + lastButton + ", lastTime " + lastTime + ", multiClickTime "
 660                                                                    + XToolkit.getMultiClickTime());

 661             if (lastWindow == this && lastButton == lbutton && (when - lastTime) < XToolkit.getMultiClickTime()) {
 662                 clickCount++;
 663             } else {
 664                 clickCount = 1;
 665                 lastWindowRef = new WeakReference(this);
 666                 lastButton = lbutton;
 667                 lastX = x;
 668                 lastY = y;
 669             }
 670             lastTime = when;
 671 
 672 
 673             /*
 674                Check for popup trigger !!
 675             */
 676             if (lbutton == getRightButtonNumber() || lbutton > 2) {
 677                 popupTrigger = true;
 678             } else {
 679                 popupTrigger = false;
 680             }


 811         synchronized (getStateLock()) {
 812             mouseAboveMe = above;
 813         }
 814     }
 815 
 816     protected void enterNotify(long window) {
 817         if (window == getWindow()) {
 818             setMouseAbove(true);
 819         }
 820     }
 821     protected void leaveNotify(long window) {
 822         if (window == getWindow()) {
 823             setMouseAbove(false);
 824         }
 825     }
 826 
 827     public void handleXCrossingEvent(XEvent xev) {
 828         super.handleXCrossingEvent(xev);
 829         XCrossingEvent xce = xev.get_xcrossing();
 830 
 831         if (eventLog.isLoggable(Level.FINEST)) eventLog.finest(xce.toString());


 832 
 833         if (xce.get_type() == XConstants.EnterNotify) {
 834             enterNotify(xce.get_window());
 835         } else { // LeaveNotify:
 836             leaveNotify(xce.get_window());
 837         }
 838 
 839         // Skip event If it was caused by a grab
 840         // This is needed because on displays with focus-follows-mouse on MousePress X system generates
 841         // two XCrossing events with mode != NormalNotify. First of them notifies that the mouse has left
 842         // current component. Second one notifies that it has entered into the same component.
 843         // This looks like the window under the mouse has actually changed and Java handle these  events
 844         // accordingly. This leads to impossibility to make a double click on Component (6404708)
 845         XWindowPeer toplevel = getToplevelXWindow();
 846         if (toplevel != null && !toplevel.isModalBlocked()){
 847             if (xce.get_mode() != NotifyNormal) {
 848                 // 6404708 : need update cursor in accordance with skipping Leave/EnterNotify event
 849                 // whereas it doesn't need to handled further.
 850                 if (xce.get_type() == EnterNotify) {
 851                     XAwtState.setComponentMouseEntered(getEventSource());


 896         long jWhen = XToolkit.nowMillisUTC_offset(xce.get_time());
 897         int modifiers = getModifiers(xce.get_state(),0,0);
 898         int clickCount = 0;
 899         boolean popupTrigger = false;
 900         int x = xce.get_x();
 901         int y = xce.get_y();
 902         if (xce.get_window() != window) {
 903             Point localXY = toLocal(xce.get_x_root(), xce.get_y_root());
 904             x = localXY.x;
 905             y = localXY.y;
 906         }
 907 
 908         // This code tracks boundary crossing and ensures MOUSE_ENTER/EXIT
 909         // are posted in alternate pairs
 910         if (compWithMouse != null) {
 911             MouseEvent me = new MouseEvent(compWithMouse,
 912                 MouseEvent.MOUSE_EXITED, jWhen, modifiers, xce.get_x(),
 913                 xce.get_y(), xce.get_x_root(), xce.get_y_root(), clickCount, popupTrigger,
 914                 MouseEvent.NOBUTTON);
 915             postEventToEventQueue(me);

 916             eventLog.finest("Clearing last window ref");

 917             lastWindowRef = null;
 918         }
 919         if (xce.get_type() == EnterNotify) {
 920             MouseEvent me = new MouseEvent(getEventSource(), MouseEvent.MOUSE_ENTERED,
 921                 jWhen, modifiers, xce.get_x(), xce.get_y(), xce.get_x_root(), xce.get_y_root(), clickCount,
 922                 popupTrigger, MouseEvent.NOBUTTON);
 923             postEventToEventQueue(me);
 924         }
 925     }
 926 
 927     public void doLayout(int x, int y, int width, int height) {}
 928 
 929     public void handleConfigureNotifyEvent(XEvent xev) {
 930         Rectangle oldBounds = getBounds();
 931 
 932         super.handleConfigureNotifyEvent(xev);
 933         if (insLog.isLoggable(Level.FINER)) {
 934             insLog.log(Level.FINER, "Configure, {0}, event disabled: {1}",
 935                        new Object[] {String.valueOf(xev), isEventDisabled(xev)});
 936         }


 961             return;
 962         }
 963         ComponentEvent ce;
 964 
 965         ce = new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_SHOWN);
 966         postEventToEventQueue(ce);
 967     }
 968 
 969     public void handleUnmapNotifyEvent(XEvent xev) {
 970         super.handleUnmapNotifyEvent(xev);
 971         if (isEventDisabled(xev)) {
 972             return;
 973         }
 974         ComponentEvent ce;
 975 
 976         ce = new ComponentEvent(target, ComponentEvent.COMPONENT_HIDDEN);
 977         postEventToEventQueue(ce);
 978     }
 979 
 980     private void dumpKeysymArray(XKeyEvent ev) {

 981         keyEventLog.fine("  "+Long.toHexString(XlibWrapper.XKeycodeToKeysym(XToolkit.getDisplay(), ev.get_keycode(), 0))+
 982                          "\n        "+Long.toHexString(XlibWrapper.XKeycodeToKeysym(XToolkit.getDisplay(), ev.get_keycode(), 1))+
 983                          "\n        "+Long.toHexString(XlibWrapper.XKeycodeToKeysym(XToolkit.getDisplay(), ev.get_keycode(), 2))+
 984                          "\n        "+Long.toHexString(XlibWrapper.XKeycodeToKeysym(XToolkit.getDisplay(), ev.get_keycode(), 3)));
 985     }

 986     /**
 987        Return unicode character or 0 if no correspondent character found.
 988        Parameter is a keysym basically from keysymdef.h
 989        XXX: how about vendor keys? Is there some with Unicode value and not in the list?
 990     */
 991     char keysymToUnicode( long keysym, int state ) {
 992         return XKeysym.convertKeysym( keysym, state );
 993     }
 994     int keyEventType2Id( int xEventType ) {
 995         return xEventType == XConstants.KeyPress ? java.awt.event.KeyEvent.KEY_PRESSED :
 996                xEventType == XConstants.KeyRelease ? java.awt.event.KeyEvent.KEY_RELEASED : 0;
 997     }
 998     static private long xkeycodeToKeysym(XKeyEvent ev) {
 999         return XKeysym.getKeysym( ev );
1000     }







1001     void logIncomingKeyEvent(XKeyEvent ev) {

1002         keyEventLog.fine("--XWindow.java:handleKeyEvent:"+ev);

1003         dumpKeysymArray(ev);

1004         keyEventLog.fine("XXXXXXXXXXXXXX javakeycode will be most probably:0x"+ Integer.toHexString(XKeysym.getJavaKeycodeOnly(ev)));
1005     }

1006     public void handleKeyPress(XEvent xev) {
1007         super.handleKeyPress(xev);
1008         XKeyEvent ev = xev.get_xkey();
1009         if (eventLog.isLoggable(Level.FINE)) eventLog.fine(ev.toString());


1010         if (isEventDisabled(xev)) {
1011             return;
1012         }
1013         handleKeyPress(ev);
1014     }
1015     // called directly from this package, unlike handleKeyRelease.
1016     // un-final it if you need to override it in a subclass.
1017     final void handleKeyPress(XKeyEvent ev) {
1018         int keycode = java.awt.event.KeyEvent.VK_UNDEFINED;
1019         long keysym[] = new long[2];
1020         char unicodeKey = 0;
1021         keysym[0] = NoSymbol;
1022 
1023         if (keyEventLog.isLoggable(Level.FINE)) {
1024             logIncomingKeyEvent( ev );
1025         }
1026         if ( //TODO check if there's an active input method instance
1027              // without calling a native method. Is it necessary though?
1028             haveCurrentX11InputMethodInstance()) {
1029             if (x11inputMethodLookupString(ev.pData, keysym)) {
1030                 if (keyEventLog.isLoggable(Level.FINE)) {
1031                     keyEventLog.fine("--XWindow.java XIM did process event; return; dec keysym processed:"+(keysym[0])+
1032                                    "; hex keysym processed:"+Long.toHexString(keysym[0])
1033                                    );
1034                 }
1035                 return;
1036             }else {
1037                 unicodeKey = keysymToUnicode( keysym[0], ev.get_state() );
1038                 if (keyEventLog.isLoggable(Level.FINE)) {
1039                     keyEventLog.fine("--XWindow.java XIM did NOT process event, hex keysym:"+Long.toHexString(keysym[0])+"\n"+
1040                                      "                                         unicode key:"+Integer.toHexString((int)unicodeKey));
1041                 }
1042             }
1043         }else  {
1044             // No input method instance found. For example, there's a Java Input Method.
1045             // Produce do-it-yourself keysym and perhaps unicode character.
1046             keysym[0] = xkeycodeToKeysym(ev);
1047             unicodeKey = keysymToUnicode( keysym[0], ev.get_state() );
1048             if (keyEventLog.isLoggable(Level.FINE)) {
1049                 keyEventLog.fine("--XWindow.java XIM is absent;             hex keysym:"+Long.toHexString(keysym[0])+"\n"+
1050                                  "                                         unicode key:"+Integer.toHexString((int)unicodeKey));
1051             }
1052         }
1053         // Keysym should be converted to Unicode, if possible and necessary,
1054         // and Java KeyEvent keycode should be calculated.
1055         // For press we should post pressed & typed Java events.
1056         //
1057         // Press event might be not processed to this time because
1058         //  (1) either XIM could not handle it or
1059         //  (2) it was Latin 1:1 mapping.
1060         //
1061         XKeysym.Keysym2JavaKeycode jkc = XKeysym.getJavaKeycode(ev);



1062         if( jkc == null ) {
1063             jkc = new XKeysym.Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDEFINED, java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN);
1064         }






1065         if (keyEventLog.isLoggable(Level.FINE)) {
1066             keyEventLog.fine(">>>Fire Event:"+
1067                (ev.get_type() == XConstants.KeyPress ? "KEY_PRESSED; " : "KEY_RELEASED; ")+
1068                "jkeycode:decimal="+jkc.getJavaKeycode()+
1069                ", hex=0x"+Integer.toHexString(jkc.getJavaKeycode())+"; "


1070             );
1071         }





1072         postKeyEvent( java.awt.event.KeyEvent.KEY_PRESSED,
1073                           ev.get_time(),
1074                           jkc.getJavaKeycode(),
1075                           (unicodeKey == 0 ? java.awt.event.KeyEvent.CHAR_UNDEFINED : unicodeKey),
1076                           jkc.getKeyLocation(),
1077                           ev.get_state(),ev.getPData(), XKeyEvent.getSize());
1078         if( unicodeKey > 0 ) {





1079                 keyEventLog.fine("fire _TYPED on "+unicodeKey);

1080                 postKeyEvent( java.awt.event.KeyEvent.KEY_TYPED,
1081                               ev.get_time(),
1082                               java.awt.event.KeyEvent.VK_UNDEFINED,
1083                               unicodeKey,
1084                               java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN,
1085                               ev.get_state(),ev.getPData(), XKeyEvent.getSize());



1086         }
1087 
1088 
1089     }
1090 
1091     public void handleKeyRelease(XEvent xev) {
1092         super.handleKeyRelease(xev);
1093         XKeyEvent ev = xev.get_xkey();
1094         if (eventLog.isLoggable(Level.FINE)) eventLog.fine(ev.toString());


1095         if (isEventDisabled(xev)) {
1096             return;
1097         }
1098         handleKeyRelease(ev);
1099     }
1100     // un-private it if you need to call it from elsewhere
1101     private void handleKeyRelease(XKeyEvent ev) {
1102         int keycode = java.awt.event.KeyEvent.VK_UNDEFINED;
1103         long keysym[] = new long[2];
1104         char unicodeKey = 0;
1105         keysym[0] = NoSymbol;
1106 
1107         if (keyEventLog.isLoggable(Level.FINE)) {
1108             logIncomingKeyEvent( ev );
1109         }
1110         // Keysym should be converted to Unicode, if possible and necessary,
1111         // and Java KeyEvent keycode should be calculated.
1112         // For release we should post released event.
1113         //
1114         XKeysym.Keysym2JavaKeycode jkc = XKeysym.getJavaKeycode(ev);




1115         if( jkc == null ) {
1116             jkc = new XKeysym.Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDEFINED, java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN);
1117         }
1118         if (keyEventLog.isLoggable(Level.FINE)) {
1119             keyEventLog.fine(">>>Fire Event:"+
1120                (ev.get_type() == XConstants.KeyPress ? "KEY_PRESSED; " : "KEY_RELEASED; ")+
1121                "jkeycode:decimal="+jkc.getJavaKeycode()+
1122                ", hex=0x"+Integer.toHexString(jkc.getJavaKeycode())+"; "


1123             );
1124         }
1125         // We obtain keysym from IM and derive unicodeKey from it for KeyPress only.
1126         // We used to cache that value and retrieve it on KeyRelease,
1127         // but in case for example of a dead key+vowel pair, a vowel after a deadkey
1128         // might never be cached before.
1129         // Also, switching between keyboard layouts, we might cache a wrong letter.
1130         // That's why we use the same procedure as if there was no IM instance: do-it-yourself unicode.
1131         unicodeKey = keysymToUnicode( xkeycodeToKeysym(ev), ev.get_state() );
1132 









1133         postKeyEvent(  java.awt.event.KeyEvent.KEY_RELEASED,
1134                           ev.get_time(),
1135                           jkc.getJavaKeycode(),
1136                           (unicodeKey == 0 ? java.awt.event.KeyEvent.CHAR_UNDEFINED : unicodeKey),
1137                           jkc.getKeyLocation(),
1138                           ev.get_state(),ev.getPData(), XKeyEvent.getSize());





1139 



1140     }
1141 
1142     /*
1143      * XmNiconic and Map/UnmapNotify (that XmNiconic relies on) are
1144      * unreliable, since mapping changes can happen for a virtual desktop
1145      * switch or MacOS style shading that became quite popular under X as
1146      * well.  Yes, it probably should not be this way, as it violates
1147      * ICCCM, but reality is that quite a lot of window managers abuse
1148      * mapping state.
1149      */
1150     int getWMState() {
1151         if (stateChanged) {
1152             stateChanged = false;
1153             WindowPropertyGetter getter =
1154                 new WindowPropertyGetter(window, XWM.XA_WM_STATE, 0, 1, false,
1155                                          XWM.XA_WM_STATE);
1156             try {
1157                 int status = getter.execute();
1158                 if (status != XConstants.Success || getter.getData() == 0) {
1159                     return savedState = XUtilConstants.WithdrawnState;


1315                                          ((XDecoratedPeer)wpeer).getContentWindow(),
1316                                          0, 0);
1317 
1318                 if (pt == null) {
1319                     pt = new Point(((XBaseWindow)wpeer).getAbsoluteX(), ((XBaseWindow)wpeer).getAbsoluteY());
1320                 }
1321                 pt.x += comp.getX();
1322                 pt.y += comp.getY();
1323                 return pt;
1324             } finally {
1325                 XToolkit.awtUnlock();
1326             }
1327         }
1328     }
1329 
1330 
1331     static void setBData(KeyEvent e, byte[] data) {
1332         AWTAccessor.getAWTEventAccessor().setBData(e, data);
1333     }
1334 
1335     public void postKeyEvent(int id, long when, int keyCode, char keyChar,
1336         int keyLocation, int state, long event, int eventSize)


1337     {
1338         long jWhen = XToolkit.nowMillisUTC_offset(when);
1339         int modifiers = getModifiers(state, 0, keyCode);

1340         KeyEvent ke = new KeyEvent((Component)getEventSource(), id, jWhen,
1341                                    modifiers, keyCode, keyChar, keyLocation);
1342         if (event != 0) {
1343             byte[] data = Native.toBytes(event, eventSize);
1344             setBData(ke, data);
1345         }





1346         postEventToEventQueue(ke);
1347     }
1348 
1349     static native int getAWTKeyCodeForKeySym(int keysym);
1350     static native int getKeySymForAWTKeyCode(int keycode);
1351 
1352     /* These two methods are actually applicable to toplevel windows only.
1353      * However, the functionality is required by both the XWindowPeer and
1354      * XWarningWindow, both of which have the XWindow as a common ancestor.
1355      * See XWM.setMotifDecor() for details.
1356      */
1357     public PropMwmHints getMWMHints() {
1358         if (mwm_hints == null) {
1359             mwm_hints = new PropMwmHints();
1360             if (!XWM.XA_MWM_HINTS.getAtomData(getWindow(), mwm_hints.pData, MWMConstants.PROP_MWM_HINTS_ELEMENTS)) {
1361                 mwm_hints.zero();
1362             }
1363         }
1364         return mwm_hints;
1365     }


   1 /*
   2  * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 370 
 371     public Rectangle getTargetBounds() {
 372         return target.getBounds();
 373     }
 374 
 375     /**
 376      * Returns true if the event has been handled and should not be
 377      * posted to Java.
 378      */
 379     boolean prePostEvent(AWTEvent e) {
 380         return false;
 381     }
 382 
 383     static void sendEvent(final AWTEvent e) {
 384         PeerEvent pe = new PeerEvent(Toolkit.getDefaultToolkit(), new Runnable() {
 385                 public void run() {
 386                     AWTAccessor.getAWTEventAccessor().setPosted(e);
 387                     ((Component)e.getSource()).dispatchEvent(e);
 388                 }
 389             }, PeerEvent.ULTIMATE_PRIORITY_EVENT);
 390         if (focusLog.isLoggable(Level.FINER) && (e instanceof FocusEvent)) {
 391             focusLog.finer("Sending " + e);
 392         }
 393         XToolkit.postEvent(XToolkit.targetToAppContext(e.getSource()), pe);
 394     }
 395 
 396 
 397 /*
 398  * Post an event to the event queue.
 399  */
 400 // NOTE: This method may be called by privileged threads.
 401 //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
 402     void postEvent(AWTEvent event) {
 403         XToolkit.postEvent(XToolkit.targetToAppContext(event.getSource()), event);
 404     }
 405 
 406     static void postEventStatic(AWTEvent event) {
 407         XToolkit.postEvent(XToolkit.targetToAppContext(event.getSource()), event);
 408     }
 409 
 410     public void postEventToEventQueue(final AWTEvent event) {
 411         //fix for 6239938 : Choice drop-down does not disappear when it loses focus, on XToolkit
 412         if (!prePostEvent(event)) {


 616                 rbutton = XlibWrapper.XGetPointerMapping(XToolkit.getDisplay(), XlibWrapper.ibuffer, 3);
 617             }
 618             finally {
 619                 XToolkit.awtUnlock();
 620             }
 621         }
 622         return rbutton;
 623     }
 624 
 625     static int getMouseMovementSmudge() {
 626         //TODO: It's possible to read corresponding settings
 627         return AWT_MULTICLICK_SMUDGE;
 628     }
 629 
 630     public void handleButtonPressRelease(XEvent xev) {
 631         super.handleButtonPressRelease(xev);
 632         XButtonEvent xbe = xev.get_xbutton();
 633         if (isEventDisabled(xev)) {
 634             return;
 635         }
 636         if (eventLog.isLoggable(Level.FINE)) {
 637             eventLog.fine(xbe.toString());
 638         }
 639         long when;
 640         int modifiers;
 641         boolean popupTrigger = false;
 642         int button=0;
 643         boolean wheel_mouse = false;
 644         long lbutton = xbe.get_button();
 645         int type = xev.get_type();
 646         when = xbe.get_time();
 647         long jWhen = XToolkit.nowMillisUTC_offset(when);
 648 
 649         int x = xbe.get_x();
 650         int y = xbe.get_y();
 651         if (xev.get_xany().get_window() != window) {
 652             Point localXY = toLocal(xbe.get_x_root(), xbe.get_y_root());
 653             x = localXY.x;
 654             y = localXY.y;
 655         }
 656 
 657         if (type == XlibWrapper.ButtonPress) {
 658             XWindow lastWindow = (lastWindowRef != null) ? ((XWindow)lastWindowRef.get()):(null);
 659             /*
 660                multiclick checking
 661             */
 662             if (eventLog.isLoggable(Level.FINEST)) {
 663                 eventLog.finest("lastWindow = " + lastWindow + ", lastButton "
 664                                 + lastButton + ", lastTime " + lastTime + ", multiClickTime "
 665                                 + XToolkit.getMultiClickTime());
 666             }
 667             if (lastWindow == this && lastButton == lbutton && (when - lastTime) < XToolkit.getMultiClickTime()) {
 668                 clickCount++;
 669             } else {
 670                 clickCount = 1;
 671                 lastWindowRef = new WeakReference(this);
 672                 lastButton = lbutton;
 673                 lastX = x;
 674                 lastY = y;
 675             }
 676             lastTime = when;
 677 
 678 
 679             /*
 680                Check for popup trigger !!
 681             */
 682             if (lbutton == getRightButtonNumber() || lbutton > 2) {
 683                 popupTrigger = true;
 684             } else {
 685                 popupTrigger = false;
 686             }


 817         synchronized (getStateLock()) {
 818             mouseAboveMe = above;
 819         }
 820     }
 821 
 822     protected void enterNotify(long window) {
 823         if (window == getWindow()) {
 824             setMouseAbove(true);
 825         }
 826     }
 827     protected void leaveNotify(long window) {
 828         if (window == getWindow()) {
 829             setMouseAbove(false);
 830         }
 831     }
 832 
 833     public void handleXCrossingEvent(XEvent xev) {
 834         super.handleXCrossingEvent(xev);
 835         XCrossingEvent xce = xev.get_xcrossing();
 836 
 837         if (eventLog.isLoggable(Level.FINEST)) {
 838             eventLog.finest(xce.toString());
 839         }
 840 
 841         if (xce.get_type() == XConstants.EnterNotify) {
 842             enterNotify(xce.get_window());
 843         } else { // LeaveNotify:
 844             leaveNotify(xce.get_window());
 845         }
 846 
 847         // Skip event If it was caused by a grab
 848         // This is needed because on displays with focus-follows-mouse on MousePress X system generates
 849         // two XCrossing events with mode != NormalNotify. First of them notifies that the mouse has left
 850         // current component. Second one notifies that it has entered into the same component.
 851         // This looks like the window under the mouse has actually changed and Java handle these  events
 852         // accordingly. This leads to impossibility to make a double click on Component (6404708)
 853         XWindowPeer toplevel = getToplevelXWindow();
 854         if (toplevel != null && !toplevel.isModalBlocked()){
 855             if (xce.get_mode() != NotifyNormal) {
 856                 // 6404708 : need update cursor in accordance with skipping Leave/EnterNotify event
 857                 // whereas it doesn't need to handled further.
 858                 if (xce.get_type() == EnterNotify) {
 859                     XAwtState.setComponentMouseEntered(getEventSource());


 904         long jWhen = XToolkit.nowMillisUTC_offset(xce.get_time());
 905         int modifiers = getModifiers(xce.get_state(),0,0);
 906         int clickCount = 0;
 907         boolean popupTrigger = false;
 908         int x = xce.get_x();
 909         int y = xce.get_y();
 910         if (xce.get_window() != window) {
 911             Point localXY = toLocal(xce.get_x_root(), xce.get_y_root());
 912             x = localXY.x;
 913             y = localXY.y;
 914         }
 915 
 916         // This code tracks boundary crossing and ensures MOUSE_ENTER/EXIT
 917         // are posted in alternate pairs
 918         if (compWithMouse != null) {
 919             MouseEvent me = new MouseEvent(compWithMouse,
 920                 MouseEvent.MOUSE_EXITED, jWhen, modifiers, xce.get_x(),
 921                 xce.get_y(), xce.get_x_root(), xce.get_y_root(), clickCount, popupTrigger,
 922                 MouseEvent.NOBUTTON);
 923             postEventToEventQueue(me);
 924             if (eventLog.isLoggable(Level.FINEST)) {
 925                 eventLog.finest("Clearing last window ref");
 926             }
 927             lastWindowRef = null;
 928         }
 929         if (xce.get_type() == EnterNotify) {
 930             MouseEvent me = new MouseEvent(getEventSource(), MouseEvent.MOUSE_ENTERED,
 931                 jWhen, modifiers, xce.get_x(), xce.get_y(), xce.get_x_root(), xce.get_y_root(), clickCount,
 932                 popupTrigger, MouseEvent.NOBUTTON);
 933             postEventToEventQueue(me);
 934         }
 935     }
 936 
 937     public void doLayout(int x, int y, int width, int height) {}
 938 
 939     public void handleConfigureNotifyEvent(XEvent xev) {
 940         Rectangle oldBounds = getBounds();
 941 
 942         super.handleConfigureNotifyEvent(xev);
 943         if (insLog.isLoggable(Level.FINER)) {
 944             insLog.log(Level.FINER, "Configure, {0}, event disabled: {1}",
 945                        new Object[] {String.valueOf(xev), isEventDisabled(xev)});
 946         }


 971             return;
 972         }
 973         ComponentEvent ce;
 974 
 975         ce = new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_SHOWN);
 976         postEventToEventQueue(ce);
 977     }
 978 
 979     public void handleUnmapNotifyEvent(XEvent xev) {
 980         super.handleUnmapNotifyEvent(xev);
 981         if (isEventDisabled(xev)) {
 982             return;
 983         }
 984         ComponentEvent ce;
 985 
 986         ce = new ComponentEvent(target, ComponentEvent.COMPONENT_HIDDEN);
 987         postEventToEventQueue(ce);
 988     }
 989 
 990     private void dumpKeysymArray(XKeyEvent ev) {
 991         if (keyEventLog.isLoggable(Level.FINE)) {
 992             keyEventLog.fine("  "+Long.toHexString(XlibWrapper.XKeycodeToKeysym(XToolkit.getDisplay(), ev.get_keycode(), 0))+
 993                              "\n        "+Long.toHexString(XlibWrapper.XKeycodeToKeysym(XToolkit.getDisplay(), ev.get_keycode(), 1))+
 994                              "\n        "+Long.toHexString(XlibWrapper.XKeycodeToKeysym(XToolkit.getDisplay(), ev.get_keycode(), 2))+
 995                              "\n        "+Long.toHexString(XlibWrapper.XKeycodeToKeysym(XToolkit.getDisplay(), ev.get_keycode(), 3)));
 996         }
 997     }
 998     /**
 999        Return unicode character or 0 if no correspondent character found.
1000        Parameter is a keysym basically from keysymdef.h
1001        XXX: how about vendor keys? Is there some with Unicode value and not in the list?
1002     */
1003     int keysymToUnicode( long keysym, int state ) {
1004         return XKeysym.convertKeysym( keysym, state );
1005     }
1006     int keyEventType2Id( int xEventType ) {
1007         return xEventType == XConstants.KeyPress ? java.awt.event.KeyEvent.KEY_PRESSED :
1008                xEventType == XConstants.KeyRelease ? java.awt.event.KeyEvent.KEY_RELEASED : 0;
1009     }
1010     static private long xkeycodeToKeysym(XKeyEvent ev) {
1011         return XKeysym.getKeysym( ev );
1012     }
1013     private long xkeycodeToPrimaryKeysym(XKeyEvent ev) {
1014         return XKeysym.xkeycode2primary_keysym( ev );
1015     }
1016     static private int primaryUnicode2JavaKeycode(int uni) {
1017         return (uni > 0? sun.awt.ExtendedKeyCodes.getExtendedKeyCodeForChar(uni) : 0);
1018         //return (uni > 0? uni + 0x01000000 : 0);
1019     }
1020     void logIncomingKeyEvent(XKeyEvent ev) {
1021         if (keyEventLog.isLoggable(Level.FINE)) {
1022             keyEventLog.fine("--XWindow.java:handleKeyEvent:"+ev);
1023         }
1024         dumpKeysymArray(ev);
1025         if (keyEventLog.isLoggable(Level.FINE)) {
1026             keyEventLog.fine("XXXXXXXXXXXXXX javakeycode will be most probably:0x"+ Integer.toHexString(XKeysym.getJavaKeycodeOnly(ev)));
1027         }
1028     }
1029     public void handleKeyPress(XEvent xev) {
1030         super.handleKeyPress(xev);
1031         XKeyEvent ev = xev.get_xkey();
1032         if (eventLog.isLoggable(Level.FINE)) {
1033             eventLog.fine(ev.toString());
1034         }
1035         if (isEventDisabled(xev)) {
1036             return;
1037         }
1038         handleKeyPress(ev);
1039     }
1040     // called directly from this package, unlike handleKeyRelease.
1041     // un-final it if you need to override it in a subclass.
1042     final void handleKeyPress(XKeyEvent ev) {
1043         int keycode = java.awt.event.KeyEvent.VK_UNDEFINED;
1044         long keysym[] = new long[2];
1045         int unicodeKey = 0;
1046         keysym[0] = NoSymbol;
1047 
1048         if (keyEventLog.isLoggable(Level.FINE)) {
1049             logIncomingKeyEvent( ev );
1050         }
1051         if ( //TODO check if there's an active input method instance
1052              // without calling a native method. Is it necessary though?
1053             haveCurrentX11InputMethodInstance()) {
1054             if (x11inputMethodLookupString(ev.pData, keysym)) {
1055                 if (keyEventLog.isLoggable(Level.FINE)) {
1056                     keyEventLog.fine("--XWindow.java XIM did process event; return; dec keysym processed:"+(keysym[0])+
1057                                    "; hex keysym processed:"+Long.toHexString(keysym[0])
1058                                    );
1059                 }
1060                 return;
1061             }else {
1062                 unicodeKey = keysymToUnicode( keysym[0], ev.get_state() );
1063                 if (keyEventLog.isLoggable(Level.FINE)) {
1064                     keyEventLog.fine("--XWindow.java XIM did NOT process event, hex keysym:"+Long.toHexString(keysym[0])+"\n"+
1065                                      "                                         unicode key:"+Integer.toHexString((int)unicodeKey));
1066                 }
1067             }
1068         } else {
1069             // No input method instance found. For example, there's a Java Input Method.
1070             // Produce do-it-yourself keysym and perhaps unicode character.
1071             keysym[0] = xkeycodeToKeysym(ev);
1072             unicodeKey = keysymToUnicode( keysym[0], ev.get_state() );
1073             if (keyEventLog.isLoggable(Level.FINE)) {
1074                 keyEventLog.fine("--XWindow.java XIM is absent;             hex keysym:"+Long.toHexString(keysym[0])+"\n"+
1075                                  "                                         unicode key:"+Integer.toHexString((int)unicodeKey));
1076             }
1077         }
1078         // Keysym should be converted to Unicode, if possible and necessary,
1079         // and Java KeyEvent keycode should be calculated.
1080         // For press we should post pressed & typed Java events.
1081         //
1082         // Press event might be not processed to this time because
1083         //  (1) either XIM could not handle it or
1084         //  (2) it was Latin 1:1 mapping.
1085         //
1086         // Preserve modifiers to get Java key code for dead keys
1087         boolean isDeadKey = isDeadKey(keysym[0]);
1088         XKeysym.Keysym2JavaKeycode jkc = isDeadKey ? XKeysym.getJavaKeycode(keysym[0])
1089                 : XKeysym.getJavaKeycode(ev);
1090         if( jkc == null ) {
1091             jkc = new XKeysym.Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDEFINED, java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN);
1092         }
1093 
1094         // Take the first keysym from a keysym array associated with the XKeyevent
1095         // and convert it to Unicode. Then, even if a Java keycode for the keystroke
1096         // is undefined, we still have a guess of what has been engraved on a keytop.
1097         int unicodeFromPrimaryKeysym = keysymToUnicode( xkeycodeToPrimaryKeysym(ev) ,0);
1098 
1099         if (keyEventLog.isLoggable(Level.FINE)) {
1100             keyEventLog.fine(">>>Fire Event:"+
1101                (ev.get_type() == XConstants.KeyPress ? "KEY_PRESSED; " : "KEY_RELEASED; ")+
1102                "jkeycode:decimal="+jkc.getJavaKeycode()+
1103                ", hex=0x"+Integer.toHexString(jkc.getJavaKeycode())+"; "+
1104                " legacy jkeycode: decimal="+XKeysym.getLegacyJavaKeycodeOnly(ev)+
1105                ", hex=0x"+Integer.toHexString(XKeysym.getLegacyJavaKeycodeOnly(ev))+"; "
1106             );
1107         }
1108 
1109         int jkeyToReturn = XKeysym.getLegacyJavaKeycodeOnly(ev); // someway backward compatible
1110         int jkeyExtended = jkc.getJavaKeycode() == java.awt.event.KeyEvent.VK_UNDEFINED ?
1111                            primaryUnicode2JavaKeycode( unicodeFromPrimaryKeysym ) :
1112                              jkc.getJavaKeycode();
1113         postKeyEvent( java.awt.event.KeyEvent.KEY_PRESSED,
1114                           ev.get_time(),
1115                           isDeadKey ? jkeyExtended : jkeyToReturn,
1116                           (unicodeKey == 0 ? java.awt.event.KeyEvent.CHAR_UNDEFINED : unicodeKey),
1117                           jkc.getKeyLocation(),
1118                           ev.get_state(),ev.getPData(), XKeyEvent.getSize(), (long)(ev.get_keycode()),
1119                           unicodeFromPrimaryKeysym,
1120                           jkeyExtended);
1121 
1122 
1123         if (unicodeKey > 0 && !isDeadKey) {
1124                 if (keyEventLog.isLoggable(Level.FINE)) {
1125                     keyEventLog.fine("fire _TYPED on "+unicodeKey);
1126                 }
1127                 postKeyEvent( java.awt.event.KeyEvent.KEY_TYPED,
1128                               ev.get_time(),
1129                               java.awt.event.KeyEvent.VK_UNDEFINED,
1130                               unicodeKey,
1131                               java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN,
1132                               ev.get_state(),ev.getPData(), XKeyEvent.getSize(), (long)0,
1133                               unicodeFromPrimaryKeysym,
1134                               java.awt.event.KeyEvent.VK_UNDEFINED);
1135 
1136         }
1137 
1138 
1139     }
1140 
1141     public void handleKeyRelease(XEvent xev) {
1142         super.handleKeyRelease(xev);
1143         XKeyEvent ev = xev.get_xkey();
1144         if (eventLog.isLoggable(Level.FINE)) {
1145             eventLog.fine(ev.toString());
1146         }
1147         if (isEventDisabled(xev)) {
1148             return;
1149         }
1150         handleKeyRelease(ev);
1151     }
1152     // un-private it if you need to call it from elsewhere
1153     private void handleKeyRelease(XKeyEvent ev) {
1154         int keycode = java.awt.event.KeyEvent.VK_UNDEFINED;
1155         int unicodeKey = 0;


1156 
1157         if (keyEventLog.isLoggable(Level.FINE)) {
1158             logIncomingKeyEvent( ev );
1159         }
1160         // Keysym should be converted to Unicode, if possible and necessary,
1161         // and Java KeyEvent keycode should be calculated.
1162         // For release we should post released event.
1163         //
1164         // Preserve modifiers to get Java key code for dead keys
1165         long keysym = xkeycodeToKeysym(ev);
1166         boolean isDeadKey = isDeadKey(keysym);
1167         XKeysym.Keysym2JavaKeycode jkc = isDeadKey ? XKeysym.getJavaKeycode(keysym)
1168                 : XKeysym.getJavaKeycode(ev);
1169         if( jkc == null ) {
1170             jkc = new XKeysym.Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDEFINED, java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN);
1171         }
1172         if (keyEventLog.isLoggable(Level.FINE)) {
1173             keyEventLog.fine(">>>Fire Event:"+
1174                (ev.get_type() == XConstants.KeyPress ? "KEY_PRESSED; " : "KEY_RELEASED; ")+
1175                "jkeycode:decimal="+jkc.getJavaKeycode()+
1176                ", hex=0x"+Integer.toHexString(jkc.getJavaKeycode())+"; "+
1177                " legacy jkeycode: decimal="+XKeysym.getLegacyJavaKeycodeOnly(ev)+
1178                ", hex=0x"+Integer.toHexString(XKeysym.getLegacyJavaKeycodeOnly(ev))+"; "
1179             );
1180         }
1181         // We obtain keysym from IM and derive unicodeKey from it for KeyPress only.
1182         // We used to cache that value and retrieve it on KeyRelease,
1183         // but in case for example of a dead key+vowel pair, a vowel after a deadkey
1184         // might never be cached before.
1185         // Also, switching between keyboard layouts, we might cache a wrong letter.
1186         // That's why we use the same procedure as if there was no IM instance: do-it-yourself unicode.
1187         unicodeKey = keysymToUnicode( xkeycodeToKeysym(ev), ev.get_state() );
1188 
1189         // Take a first keysym from a keysym array associated with the XKeyevent
1190         // and convert it to Unicode. Then, even if Java keycode for the keystroke
1191         // is undefined, we still will have a guess of what was engraved on a keytop.
1192         int unicodeFromPrimaryKeysym = keysymToUnicode( xkeycodeToPrimaryKeysym(ev) ,0);
1193 
1194         int jkeyToReturn = XKeysym.getLegacyJavaKeycodeOnly(ev); // someway backward compatible
1195         int jkeyExtended = jkc.getJavaKeycode() == java.awt.event.KeyEvent.VK_UNDEFINED ?
1196                            primaryUnicode2JavaKeycode( unicodeFromPrimaryKeysym ) :
1197                              jkc.getJavaKeycode();
1198         postKeyEvent(  java.awt.event.KeyEvent.KEY_RELEASED,
1199                           ev.get_time(),
1200                           isDeadKey ? jkeyExtended : jkeyToReturn,
1201                           (unicodeKey == 0 ? java.awt.event.KeyEvent.CHAR_UNDEFINED : unicodeKey),
1202                           jkc.getKeyLocation(),
1203                           ev.get_state(),ev.getPData(), XKeyEvent.getSize(), (long)(ev.get_keycode()),
1204                           unicodeFromPrimaryKeysym,
1205                           jkeyExtended);
1206 
1207 
1208     }
1209 
1210 
1211     private boolean isDeadKey(long keysym){
1212         return XKeySymConstants.XK_dead_grave <= keysym && keysym <= XKeySymConstants.XK_dead_semivoiced_sound;
1213     }
1214 
1215     /*
1216      * XmNiconic and Map/UnmapNotify (that XmNiconic relies on) are
1217      * unreliable, since mapping changes can happen for a virtual desktop
1218      * switch or MacOS style shading that became quite popular under X as
1219      * well.  Yes, it probably should not be this way, as it violates
1220      * ICCCM, but reality is that quite a lot of window managers abuse
1221      * mapping state.
1222      */
1223     int getWMState() {
1224         if (stateChanged) {
1225             stateChanged = false;
1226             WindowPropertyGetter getter =
1227                 new WindowPropertyGetter(window, XWM.XA_WM_STATE, 0, 1, false,
1228                                          XWM.XA_WM_STATE);
1229             try {
1230                 int status = getter.execute();
1231                 if (status != XConstants.Success || getter.getData() == 0) {
1232                     return savedState = XUtilConstants.WithdrawnState;


1388                                          ((XDecoratedPeer)wpeer).getContentWindow(),
1389                                          0, 0);
1390 
1391                 if (pt == null) {
1392                     pt = new Point(((XBaseWindow)wpeer).getAbsoluteX(), ((XBaseWindow)wpeer).getAbsoluteY());
1393                 }
1394                 pt.x += comp.getX();
1395                 pt.y += comp.getY();
1396                 return pt;
1397             } finally {
1398                 XToolkit.awtUnlock();
1399             }
1400         }
1401     }
1402 
1403 
1404     static void setBData(KeyEvent e, byte[] data) {
1405         AWTAccessor.getAWTEventAccessor().setBData(e, data);
1406     }
1407 
1408     public void postKeyEvent(int id, long when, int keyCode, int keyChar,
1409         int keyLocation, int state, long event, int eventSize, long rawCode,
1410         int unicodeFromPrimaryKeysym, int extendedKeyCode)
1411 
1412     {
1413         long jWhen = XToolkit.nowMillisUTC_offset(when);
1414         int modifiers = getModifiers(state, 0, keyCode);
1415 
1416         KeyEvent ke = new KeyEvent((Component)getEventSource(), id, jWhen,
1417                                    modifiers, keyCode, (char)keyChar, keyLocation);
1418         if (event != 0) {
1419             byte[] data = Native.toBytes(event, eventSize);
1420             setBData(ke, data);
1421         }
1422 
1423         AWTAccessor.KeyEventAccessor kea = AWTAccessor.getKeyEventAccessor();
1424         kea.setRawCode(ke, rawCode);
1425         kea.setPrimaryLevelUnicode(ke, (long)unicodeFromPrimaryKeysym);
1426         kea.setExtendedKeyCode(ke, (long)extendedKeyCode);
1427         postEventToEventQueue(ke);
1428     }
1429 
1430     static native int getAWTKeyCodeForKeySym(int keysym);
1431     static native int getKeySymForAWTKeyCode(int keycode);
1432 
1433     /* These two methods are actually applicable to toplevel windows only.
1434      * However, the functionality is required by both the XWindowPeer and
1435      * XWarningWindow, both of which have the XWindow as a common ancestor.
1436      * See XWM.setMotifDecor() for details.
1437      */
1438     public PropMwmHints getMWMHints() {
1439         if (mwm_hints == null) {
1440             mwm_hints = new PropMwmHints();
1441             if (!XWM.XA_MWM_HINTS.getAtomData(getWindow(), mwm_hints.pData, MWMConstants.PROP_MWM_HINTS_ELEMENTS)) {
1442                 mwm_hints.zero();
1443             }
1444         }
1445         return mwm_hints;
1446     }


< prev index next >