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