43 #include "awt_Font.h" |
43 #include "awt_Font.h" |
44 |
44 |
45 #include "sun_awt_X11_XToolkit.h" |
45 #include "sun_awt_X11_XToolkit.h" |
46 #include "java_awt_SystemColor.h" |
46 #include "java_awt_SystemColor.h" |
47 #include "java_awt_TrayIcon.h" |
47 #include "java_awt_TrayIcon.h" |
|
48 #include <X11/extensions/XTest.h> |
48 |
49 |
49 uint32_t awt_NumLockMask = 0; |
50 uint32_t awt_NumLockMask = 0; |
50 Boolean awt_ModLockIsShiftLock = False; |
51 Boolean awt_ModLockIsShiftLock = False; |
|
52 |
|
53 static int32_t num_buttons = 0; |
|
54 int32_t getNumButtons(); |
51 |
55 |
52 extern JavaVM *jvm; |
56 extern JavaVM *jvm; |
53 |
57 |
54 // Tracing level |
58 // Tracing level |
55 static int tracing = 0; |
59 static int tracing = 0; |
906 AWT_LOCK(); |
910 AWT_LOCK(); |
907 XFreeCursor(awt_display, xcursor); |
911 XFreeCursor(awt_display, xcursor); |
908 AWT_UNLOCK(); |
912 AWT_UNLOCK(); |
909 } |
913 } |
910 } |
914 } |
|
915 |
|
916 |
|
917 /* |
|
918 * Class: sun_awt_X11_XToolkit |
|
919 * Method: getNumberOfButtonsImpl |
|
920 * Signature: ()I |
|
921 */ |
|
922 JNIEXPORT jint JNICALL Java_sun_awt_X11_XToolkit_getNumberOfButtonsImpl |
|
923 (JNIEnv * env, jobject cls){ |
|
924 if (num_buttons == 0) { |
|
925 num_buttons = getNumButtons(); |
|
926 } |
|
927 return num_buttons; |
|
928 } |
|
929 |
|
930 int32_t getNumButtons() { |
|
931 int32_t major_opcode, first_event, first_error; |
|
932 int32_t xinputAvailable; |
|
933 int32_t numDevices, devIdx, clsIdx; |
|
934 XDeviceInfo* devices; |
|
935 XDeviceInfo* aDevice; |
|
936 XButtonInfo* bInfo; |
|
937 int32_t local_num_buttons = 0; |
|
938 |
|
939 /* 4700242: |
|
940 * If XTest is asked to press a non-existant mouse button |
|
941 * (i.e. press Button3 on a system configured with a 2-button mouse), |
|
942 * then a crash may happen. To avoid this, we use the XInput |
|
943 * extension to query for the number of buttons on the XPointer, and check |
|
944 * before calling XTestFakeButtonEvent(). |
|
945 */ |
|
946 xinputAvailable = XQueryExtension(awt_display, INAME, &major_opcode, &first_event, &first_error); |
|
947 DTRACE_PRINTLN3("RobotPeer: XQueryExtension(XINPUT) returns major_opcode = %d, first_event = %d, first_error = %d", |
|
948 major_opcode, first_event, first_error); |
|
949 if (xinputAvailable) { |
|
950 devices = XListInputDevices(awt_display, &numDevices); |
|
951 for (devIdx = 0; devIdx < numDevices; devIdx++) { |
|
952 aDevice = &(devices[devIdx]); |
|
953 if (aDevice->use == IsXExtensionPointer) { |
|
954 for (clsIdx = 0; clsIdx < aDevice->num_classes; clsIdx++) { |
|
955 if (aDevice->inputclassinfo[clsIdx].class == ButtonClass) { |
|
956 bInfo = (XButtonInfo*)(&(aDevice->inputclassinfo[clsIdx])); |
|
957 local_num_buttons = bInfo->num_buttons; |
|
958 DTRACE_PRINTLN1("RobotPeer: XPointer has %d buttons", num_buttons); |
|
959 break; |
|
960 } |
|
961 } |
|
962 break; |
|
963 } |
|
964 if (local_num_buttons <= 0 ) { |
|
965 if (aDevice->use == IsXPointer) { |
|
966 for (clsIdx = 0; clsIdx < aDevice->num_classes; clsIdx++) { |
|
967 if (aDevice->inputclassinfo[clsIdx].class == ButtonClass) { |
|
968 bInfo = (XButtonInfo*)(&(aDevice->inputclassinfo[clsIdx])); |
|
969 local_num_buttons = bInfo->num_buttons; |
|
970 DTRACE_PRINTLN1("RobotPeer: XPointer has %d buttons", num_buttons); |
|
971 break; |
|
972 } |
|
973 } |
|
974 break; |
|
975 } |
|
976 } |
|
977 } |
|
978 |
|
979 XFreeDeviceList(devices); |
|
980 } |
|
981 else { |
|
982 DTRACE_PRINTLN1("RobotPeer: XINPUT extension is unavailable, assuming %d mouse buttons", num_buttons); |
|
983 } |
|
984 if (local_num_buttons == 0 ) { |
|
985 local_num_buttons = 3; |
|
986 } |
|
987 |
|
988 return local_num_buttons; |
|
989 } |