jdk/src/solaris/native/sun/awt/canvas.c
changeset 1192 715cf9378c53
parent 1051 90cf935adb35
parent 1191 f142c1da78c2
child 1193 41afb8ee8f45
equal deleted inserted replaced
1051:90cf935adb35 1192:715cf9378c53
     1 /*
       
     2  * Copyright 1995-2005 Sun Microsystems, Inc.  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.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 #ifdef HEADLESS
       
    27     #error This file should not be included in headless library
       
    28 #endif
       
    29 
       
    30 #include "awt_p.h"
       
    31 #include <sys/time.h> /* timeval */
       
    32 
       
    33 #define XK_KATAKANA
       
    34 #include <X11/keysym.h>     /* standard X keysyms */
       
    35 #include <X11/DECkeysym.h>  /* DEC vendor-specific */
       
    36 #include <X11/Sunkeysym.h>  /* Sun vendor-specific */
       
    37 #include <X11/ap_keysym.h>  /* Apollo (HP) vendor-specific */
       
    38 /*
       
    39  * #include <X11/HPkeysym.h>    HP vendor-specific
       
    40  * I checked HPkeysym.h into the workspace because it ships
       
    41  * with X11R6.4.2 (and later) but not with X11R6.4.1.
       
    42  * So, it ought to ship with Solaris 9, but not Solaris 8.
       
    43  * Same deal for Linux - newer versions of XFree have it.
       
    44  *
       
    45  * Note: this is mainly done for the hp keysyms; it does NOT
       
    46  * give us the osf keysyms that are also defined in HPkeysym.h.
       
    47  * This is because we are already getting /Xm/VirtKeys.h
       
    48  * from awt_p.h <- /Xm/Xm.h <- /Xm/VirtKeys.h, and VirtKeys.h
       
    49  * #defines _OSF_Keysyms before we get here.  We are
       
    50  * missing a couple of osf keysyms because of this,
       
    51  * so I have #defined them below.
       
    52  */
       
    53 #include "HPkeysym.h"   /* HP vendor-specific */
       
    54 
       
    55 #include <Xm/Display.h>
       
    56 #include <ctype.h>
       
    57 #include "java_awt_Frame.h"
       
    58 #include "java_awt_Component.h"
       
    59 #include "java_awt_AWTEvent.h"
       
    60 #include "java_awt_event_KeyEvent.h"
       
    61 #include "java_awt_event_FocusEvent.h"
       
    62 #include "java_awt_event_MouseEvent.h"
       
    63 #include "java_awt_event_MouseWheelEvent.h"
       
    64 #include "java_awt_event_InputEvent.h"
       
    65 #include "java_awt_event_WindowEvent.h"
       
    66 #include "sun_awt_motif_MComponentPeer.h"
       
    67 #include "color.h"
       
    68 #include "canvas.h"
       
    69 #include "awt_Cursor.h"
       
    70 #include "VDrawingArea.h"
       
    71 #include "XDrawingArea.h"
       
    72 #include "awt_Component.h"
       
    73 #include "awt_AWTEvent.h"
       
    74 #include "awt_Event.h"
       
    75 #include "awt_KeyboardFocusManager.h"
       
    76 #include "awt_MToolkit.h"
       
    77 #include "awt_TopLevel.h"
       
    78 #include "awt_util.h"
       
    79 
       
    80 #include <jni.h>
       
    81 #include <jni_util.h>
       
    82 #include <jvm.h>
       
    83 #include <jawt.h>
       
    84 
       
    85 #ifdef NDEBUG   /* NDEBUG overrides DEBUG */
       
    86 #undef DEBUG
       
    87 #endif
       
    88 
       
    89 /*
       
    90  * Two osf keys are not defined in standard keysym.h,
       
    91  * /Xm/VirtKeys.h, or HPkeysym.h, so I added them below.
       
    92  * I found them in /usr/openwin/lib/X11/XKeysymDB
       
    93  */
       
    94 #ifndef osfXK_Prior
       
    95 #define osfXK_Prior 0x1004FF55
       
    96 #endif
       
    97 #ifndef osfXK_Next
       
    98 #define osfXK_Next 0x1004FF56
       
    99 #endif
       
   100 /*
       
   101  * osfXK_Escape is defined in HPkeysym.h, but not in
       
   102  * /Xm/VirtKeys.h, so I added it below.  It is also in
       
   103  * /usr/openwin/lib/X11/XKeysymDB
       
   104  * Note: it is in /Xm/VirtKeys.h in the AWT motif workspace,
       
   105  * but not in /usr/local/Motif/include/Xm/VirtKeys.h
       
   106  * on the Solaris 7, 8, or 9 machines I tried.
       
   107  */
       
   108 #ifndef osfXK_Escape
       
   109 #define osfXK_Escape 0x1004FF1B
       
   110 #endif
       
   111 
       
   112 extern struct MComponentPeerIDs mComponentPeerIDs;
       
   113 extern struct AWTEventIDs awtEventIDs;
       
   114 extern struct KeyEventIDs keyEventIDs;
       
   115 extern struct InputEventIDs inputEventIDs;
       
   116 extern struct ComponentIDs componentIDs;
       
   117 extern struct KeyboardFocusManagerIDs keyboardFocusManagerIDs;
       
   118 
       
   119 #ifdef DEBUG
       
   120 static Boolean debugKeys = False;
       
   121 #endif
       
   122 
       
   123 jint awt_multiclick_smudge = 4;
       
   124 
       
   125 extern Widget drag_source;
       
   126 
       
   127 Widget prevWidget = NULL; /* for bug fix 4017222 */
       
   128 
       
   129 FocusListElt *focusList = NULL, *focusListEnd = NULL;
       
   130 
       
   131 jweak forGained = NULL;
       
   132 
       
   133 extern Boolean scrollBugWorkAround;
       
   134 extern jobject currentX11InputMethodInstance;
       
   135 extern Window  currentFocusWindow;
       
   136 extern Boolean awt_x11inputmethod_lookupString(XKeyPressedEvent *, KeySym *);
       
   137 Boolean awt_UseType4Patch = True;
       
   138 Boolean awt_ServerDetected = False;
       
   139 Boolean awt_IsXsun = False;
       
   140 Boolean awt_UseXKB = False;
       
   141 
       
   142 void awt_post_java_key_event(XtPointer client_data, jint id,
       
   143                              XEvent *xevent, Time when, jint keycode,
       
   144                              jchar keychar, jint modifiers,
       
   145                              jint keyLocation, XEvent *anEvent);
       
   146 void awt_post_java_focus_event(XtPointer client_data, jint id, jobject cause,
       
   147                                XEvent *event);
       
   148 void awt_post_java_mouse_event(XtPointer client_data, jint id,
       
   149                                XEvent *event, Time when, jint modifiers,
       
   150                                jint x, jint y,
       
   151                                jint xAbs, jint yAbs,
       
   152                                jint clickcount, Boolean popuptrigger,
       
   153                                jint wheelAmt, jint button);
       
   154 
       
   155 typedef struct KEYMAP_ENTRY {
       
   156     jint awtKey;
       
   157     KeySym x11Key;
       
   158     Boolean mapsToUnicodeChar;
       
   159     jint keyLocation;
       
   160 } KeymapEntry;
       
   161 
       
   162 /* NB: XK_R? keysyms are for Type 4 keyboards.
       
   163  * The corresponding XK_F? keysyms are for Type 5
       
   164  *
       
   165  * Note: this table must be kept in sorted order, since it is traversed
       
   166  * according to both Java keycode and X keysym.  There are a number of
       
   167  * keycodes that map to more than one corresponding keysym, and we need
       
   168  * to choose the right one.  Unfortunately, there are some keysyms that
       
   169  * can map to more than one keycode, depending on what kind of keyboard
       
   170  * is in use (e.g. F11 and F12).
       
   171  */
       
   172 
       
   173 KeymapEntry keymapTable[] =
       
   174 {
       
   175     {java_awt_event_KeyEvent_VK_A, XK_a, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   176     {java_awt_event_KeyEvent_VK_B, XK_b, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   177     {java_awt_event_KeyEvent_VK_C, XK_c, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   178     {java_awt_event_KeyEvent_VK_D, XK_d, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   179     {java_awt_event_KeyEvent_VK_E, XK_e, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   180     {java_awt_event_KeyEvent_VK_F, XK_f, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   181     {java_awt_event_KeyEvent_VK_G, XK_g, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   182     {java_awt_event_KeyEvent_VK_H, XK_h, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   183     {java_awt_event_KeyEvent_VK_I, XK_i, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   184     {java_awt_event_KeyEvent_VK_J, XK_j, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   185     {java_awt_event_KeyEvent_VK_K, XK_k, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   186     {java_awt_event_KeyEvent_VK_L, XK_l, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   187     {java_awt_event_KeyEvent_VK_M, XK_m, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   188     {java_awt_event_KeyEvent_VK_N, XK_n, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   189     {java_awt_event_KeyEvent_VK_O, XK_o, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   190     {java_awt_event_KeyEvent_VK_P, XK_p, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   191     {java_awt_event_KeyEvent_VK_Q, XK_q, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   192     {java_awt_event_KeyEvent_VK_R, XK_r, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   193     {java_awt_event_KeyEvent_VK_S, XK_s, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   194     {java_awt_event_KeyEvent_VK_T, XK_t, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   195     {java_awt_event_KeyEvent_VK_U, XK_u, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   196     {java_awt_event_KeyEvent_VK_V, XK_v, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   197     {java_awt_event_KeyEvent_VK_W, XK_w, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   198     {java_awt_event_KeyEvent_VK_X, XK_x, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   199     {java_awt_event_KeyEvent_VK_Y, XK_y, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   200     {java_awt_event_KeyEvent_VK_Z, XK_z, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   201 
       
   202     /* TTY Function keys */
       
   203     {java_awt_event_KeyEvent_VK_BACK_SPACE, XK_BackSpace, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   204     {java_awt_event_KeyEvent_VK_TAB, XK_Tab, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   205     {java_awt_event_KeyEvent_VK_CLEAR, XK_Clear, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   206     {java_awt_event_KeyEvent_VK_ENTER, XK_Return, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   207     {java_awt_event_KeyEvent_VK_ENTER, XK_Linefeed, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   208     {java_awt_event_KeyEvent_VK_PAUSE, XK_Pause, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   209     {java_awt_event_KeyEvent_VK_PAUSE, XK_F21, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   210     {java_awt_event_KeyEvent_VK_PAUSE, XK_R1, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   211     {java_awt_event_KeyEvent_VK_SCROLL_LOCK, XK_Scroll_Lock, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   212     {java_awt_event_KeyEvent_VK_SCROLL_LOCK, XK_F23, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   213     {java_awt_event_KeyEvent_VK_SCROLL_LOCK, XK_R3, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   214     {java_awt_event_KeyEvent_VK_ESCAPE, XK_Escape, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   215 
       
   216     /* Other vendor-specific versions of TTY Function keys */
       
   217     {java_awt_event_KeyEvent_VK_BACK_SPACE, osfXK_BackSpace, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   218     {java_awt_event_KeyEvent_VK_CLEAR, osfXK_Clear, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   219     {java_awt_event_KeyEvent_VK_ESCAPE, osfXK_Escape, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   220 
       
   221     /* Modifier keys */
       
   222     {java_awt_event_KeyEvent_VK_SHIFT, XK_Shift_L, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_LEFT},
       
   223     {java_awt_event_KeyEvent_VK_SHIFT, XK_Shift_R, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_RIGHT},
       
   224     {java_awt_event_KeyEvent_VK_CONTROL, XK_Control_L, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_LEFT},
       
   225     {java_awt_event_KeyEvent_VK_CONTROL, XK_Control_R, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_RIGHT},
       
   226     {java_awt_event_KeyEvent_VK_ALT, XK_Alt_L, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_LEFT},
       
   227     {java_awt_event_KeyEvent_VK_ALT, XK_Alt_R, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_RIGHT},
       
   228     {java_awt_event_KeyEvent_VK_META, XK_Meta_L, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_LEFT},
       
   229     {java_awt_event_KeyEvent_VK_META, XK_Meta_R, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_RIGHT},
       
   230     {java_awt_event_KeyEvent_VK_CAPS_LOCK, XK_Caps_Lock, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   231 
       
   232     /* Misc Functions */
       
   233     {java_awt_event_KeyEvent_VK_PRINTSCREEN, XK_Print, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   234     {java_awt_event_KeyEvent_VK_PRINTSCREEN, XK_F22, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   235     {java_awt_event_KeyEvent_VK_PRINTSCREEN, XK_R2, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   236     {java_awt_event_KeyEvent_VK_CANCEL, XK_Cancel, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   237     {java_awt_event_KeyEvent_VK_HELP, XK_Help, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   238     {java_awt_event_KeyEvent_VK_NUM_LOCK, XK_Num_Lock, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   239 
       
   240     /* Other vendor-specific versions of Misc Functions */
       
   241     {java_awt_event_KeyEvent_VK_CANCEL, osfXK_Cancel, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   242     {java_awt_event_KeyEvent_VK_HELP, osfXK_Help, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   243 
       
   244     /* Rectangular Navigation Block */
       
   245     {java_awt_event_KeyEvent_VK_HOME, XK_Home, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   246     {java_awt_event_KeyEvent_VK_HOME, XK_R7, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   247     {java_awt_event_KeyEvent_VK_PAGE_UP, XK_Page_Up, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   248     {java_awt_event_KeyEvent_VK_PAGE_UP, XK_Prior, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   249     {java_awt_event_KeyEvent_VK_PAGE_UP, XK_R9, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   250     {java_awt_event_KeyEvent_VK_PAGE_DOWN, XK_Page_Down, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   251     {java_awt_event_KeyEvent_VK_PAGE_DOWN, XK_Next, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   252     {java_awt_event_KeyEvent_VK_PAGE_DOWN, XK_R15, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   253     {java_awt_event_KeyEvent_VK_END, XK_End, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   254     {java_awt_event_KeyEvent_VK_END, XK_R13, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   255     {java_awt_event_KeyEvent_VK_INSERT, XK_Insert, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   256     {java_awt_event_KeyEvent_VK_DELETE, XK_Delete, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   257 
       
   258     /* Keypad equivalents of Rectangular Navigation Block */
       
   259     {java_awt_event_KeyEvent_VK_HOME, XK_KP_Home, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   260     {java_awt_event_KeyEvent_VK_PAGE_UP, XK_KP_Page_Up, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   261     {java_awt_event_KeyEvent_VK_PAGE_UP, XK_KP_Prior, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   262     {java_awt_event_KeyEvent_VK_PAGE_DOWN, XK_KP_Page_Down, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   263     {java_awt_event_KeyEvent_VK_PAGE_DOWN, XK_KP_Next, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   264     {java_awt_event_KeyEvent_VK_END, XK_KP_End, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   265     {java_awt_event_KeyEvent_VK_INSERT, XK_KP_Insert, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   266     {java_awt_event_KeyEvent_VK_DELETE, XK_KP_Delete, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   267 
       
   268     /* Other vendor-specific Rectangular Navigation Block */
       
   269     {java_awt_event_KeyEvent_VK_PAGE_UP, osfXK_PageUp, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   270     {java_awt_event_KeyEvent_VK_PAGE_UP, osfXK_Prior, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   271     {java_awt_event_KeyEvent_VK_PAGE_DOWN, osfXK_PageDown, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   272     {java_awt_event_KeyEvent_VK_PAGE_DOWN, osfXK_Next, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   273     {java_awt_event_KeyEvent_VK_END, osfXK_EndLine, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   274     {java_awt_event_KeyEvent_VK_INSERT, osfXK_Insert, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   275     {java_awt_event_KeyEvent_VK_DELETE, osfXK_Delete, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   276 
       
   277     /* Triangular Navigation Block */
       
   278     {java_awt_event_KeyEvent_VK_LEFT, XK_Left, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   279     {java_awt_event_KeyEvent_VK_UP, XK_Up, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   280     {java_awt_event_KeyEvent_VK_RIGHT, XK_Right, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   281     {java_awt_event_KeyEvent_VK_DOWN, XK_Down, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   282 
       
   283     /* Keypad equivalents of Triangular Navigation Block */
       
   284     {java_awt_event_KeyEvent_VK_KP_LEFT, XK_KP_Left, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   285     {java_awt_event_KeyEvent_VK_KP_UP, XK_KP_Up, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   286     {java_awt_event_KeyEvent_VK_KP_RIGHT, XK_KP_Right, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   287     {java_awt_event_KeyEvent_VK_KP_DOWN, XK_KP_Down, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   288 
       
   289     /* Other vendor-specific Triangular Navigation Block */
       
   290     {java_awt_event_KeyEvent_VK_LEFT, osfXK_Left, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   291     {java_awt_event_KeyEvent_VK_UP, osfXK_Up, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   292     {java_awt_event_KeyEvent_VK_RIGHT, osfXK_Right, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   293     {java_awt_event_KeyEvent_VK_DOWN, osfXK_Down, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   294 
       
   295     /* Remaining Cursor control & motion */
       
   296     {java_awt_event_KeyEvent_VK_BEGIN, XK_Begin, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   297     {java_awt_event_KeyEvent_VK_BEGIN, XK_KP_Begin, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   298 
       
   299     {java_awt_event_KeyEvent_VK_0, XK_0, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   300     {java_awt_event_KeyEvent_VK_1, XK_1, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   301     {java_awt_event_KeyEvent_VK_2, XK_2, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   302     {java_awt_event_KeyEvent_VK_3, XK_3, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   303     {java_awt_event_KeyEvent_VK_4, XK_4, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   304     {java_awt_event_KeyEvent_VK_5, XK_5, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   305     {java_awt_event_KeyEvent_VK_6, XK_6, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   306     {java_awt_event_KeyEvent_VK_7, XK_7, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   307     {java_awt_event_KeyEvent_VK_8, XK_8, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   308     {java_awt_event_KeyEvent_VK_9, XK_9, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   309 
       
   310     {java_awt_event_KeyEvent_VK_SPACE, XK_space, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   311     {java_awt_event_KeyEvent_VK_EXCLAMATION_MARK, XK_exclam, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   312     {java_awt_event_KeyEvent_VK_QUOTEDBL, XK_quotedbl, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   313     {java_awt_event_KeyEvent_VK_NUMBER_SIGN, XK_numbersign, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   314     {java_awt_event_KeyEvent_VK_DOLLAR, XK_dollar, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   315     {java_awt_event_KeyEvent_VK_AMPERSAND, XK_ampersand, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   316     {java_awt_event_KeyEvent_VK_QUOTE, XK_apostrophe, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   317     {java_awt_event_KeyEvent_VK_LEFT_PARENTHESIS, XK_parenleft, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   318     {java_awt_event_KeyEvent_VK_RIGHT_PARENTHESIS, XK_parenright, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   319     {java_awt_event_KeyEvent_VK_ASTERISK, XK_asterisk, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   320     {java_awt_event_KeyEvent_VK_PLUS, XK_plus, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   321     {java_awt_event_KeyEvent_VK_COMMA, XK_comma, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   322     {java_awt_event_KeyEvent_VK_MINUS, XK_minus, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   323     {java_awt_event_KeyEvent_VK_PERIOD, XK_period, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   324     {java_awt_event_KeyEvent_VK_SLASH, XK_slash, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   325 
       
   326     {java_awt_event_KeyEvent_VK_COLON, XK_colon, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   327     {java_awt_event_KeyEvent_VK_SEMICOLON, XK_semicolon, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   328     {java_awt_event_KeyEvent_VK_LESS, XK_less, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   329     {java_awt_event_KeyEvent_VK_EQUALS, XK_equal, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   330     {java_awt_event_KeyEvent_VK_GREATER, XK_greater, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   331 
       
   332     {java_awt_event_KeyEvent_VK_AT, XK_at, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   333 
       
   334     {java_awt_event_KeyEvent_VK_OPEN_BRACKET, XK_bracketleft, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   335     {java_awt_event_KeyEvent_VK_BACK_SLASH, XK_backslash, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   336     {java_awt_event_KeyEvent_VK_CLOSE_BRACKET, XK_bracketright, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   337     {java_awt_event_KeyEvent_VK_CIRCUMFLEX, XK_asciicircum, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   338     {java_awt_event_KeyEvent_VK_UNDERSCORE, XK_underscore, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   339     {java_awt_event_KeyEvent_VK_BACK_QUOTE, XK_grave, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   340 
       
   341     {java_awt_event_KeyEvent_VK_BRACELEFT, XK_braceleft, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   342     {java_awt_event_KeyEvent_VK_BRACERIGHT, XK_braceright, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   343 
       
   344     {java_awt_event_KeyEvent_VK_INVERTED_EXCLAMATION_MARK, XK_exclamdown, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   345 
       
   346     /* Remaining Numeric Keypad Keys */
       
   347     {java_awt_event_KeyEvent_VK_NUMPAD0, XK_KP_0, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   348     {java_awt_event_KeyEvent_VK_NUMPAD1, XK_KP_1, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   349     {java_awt_event_KeyEvent_VK_NUMPAD2, XK_KP_2, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   350     {java_awt_event_KeyEvent_VK_NUMPAD3, XK_KP_3, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   351     {java_awt_event_KeyEvent_VK_NUMPAD4, XK_KP_4, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   352     {java_awt_event_KeyEvent_VK_NUMPAD5, XK_KP_5, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   353     {java_awt_event_KeyEvent_VK_NUMPAD6, XK_KP_6, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   354     {java_awt_event_KeyEvent_VK_NUMPAD7, XK_KP_7, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   355     {java_awt_event_KeyEvent_VK_NUMPAD8, XK_KP_8, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   356     {java_awt_event_KeyEvent_VK_NUMPAD9, XK_KP_9, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   357     {java_awt_event_KeyEvent_VK_SPACE, XK_KP_Space, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   358     {java_awt_event_KeyEvent_VK_TAB, XK_KP_Tab, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   359     {java_awt_event_KeyEvent_VK_ENTER, XK_KP_Enter, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   360     {java_awt_event_KeyEvent_VK_EQUALS, XK_KP_Equal, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   361     {java_awt_event_KeyEvent_VK_EQUALS, XK_R4, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   362     {java_awt_event_KeyEvent_VK_MULTIPLY, XK_KP_Multiply, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   363     {java_awt_event_KeyEvent_VK_MULTIPLY, XK_F26, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   364     {java_awt_event_KeyEvent_VK_MULTIPLY, XK_R6, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   365     {java_awt_event_KeyEvent_VK_ADD, XK_KP_Add, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   366     {java_awt_event_KeyEvent_VK_SEPARATOR, XK_KP_Separator, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   367     {java_awt_event_KeyEvent_VK_SUBTRACT, XK_KP_Subtract, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   368     {java_awt_event_KeyEvent_VK_SUBTRACT, XK_F24, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   369     {java_awt_event_KeyEvent_VK_DECIMAL, XK_KP_Decimal, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   370     {java_awt_event_KeyEvent_VK_DIVIDE, XK_KP_Divide, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   371     {java_awt_event_KeyEvent_VK_DIVIDE, XK_F25, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   372     {java_awt_event_KeyEvent_VK_DIVIDE, XK_R5, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
       
   373 
       
   374     /* Function Keys */
       
   375     {java_awt_event_KeyEvent_VK_F1, XK_F1, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   376     {java_awt_event_KeyEvent_VK_F2, XK_F2, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   377     {java_awt_event_KeyEvent_VK_F3, XK_F3, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   378     {java_awt_event_KeyEvent_VK_F4, XK_F4, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   379     {java_awt_event_KeyEvent_VK_F5, XK_F5, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   380     {java_awt_event_KeyEvent_VK_F6, XK_F6, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   381     {java_awt_event_KeyEvent_VK_F7, XK_F7, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   382     {java_awt_event_KeyEvent_VK_F8, XK_F8, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   383     {java_awt_event_KeyEvent_VK_F9, XK_F9, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   384     {java_awt_event_KeyEvent_VK_F10, XK_F10, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   385     {java_awt_event_KeyEvent_VK_F11, XK_F11, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   386     {java_awt_event_KeyEvent_VK_F12, XK_F12, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   387 
       
   388     /* Sun vendor-specific version of F11 and F12 */
       
   389     {java_awt_event_KeyEvent_VK_F11, SunXK_F36, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   390     {java_awt_event_KeyEvent_VK_F12, SunXK_F37, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   391 
       
   392     /* X11 keysym names for input method related keys don't always
       
   393      * match keytop engravings or Java virtual key names, so here we
       
   394      * only map constants that we've found on real keyboards.
       
   395      */
       
   396     /* Type 5c Japanese keyboard: kakutei */
       
   397     {java_awt_event_KeyEvent_VK_ACCEPT, XK_Execute, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   398     /* Type 5c Japanese keyboard: henkan */
       
   399     {java_awt_event_KeyEvent_VK_CONVERT, XK_Kanji, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   400     /* Type 5c Japanese keyboard: nihongo */
       
   401     {java_awt_event_KeyEvent_VK_INPUT_METHOD_ON_OFF, XK_Henkan_Mode, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   402     /* VK_KANA_LOCK is handled separately because it generates the
       
   403      * same keysym as ALT_GRAPH in spite of its different behavior.
       
   404      */
       
   405 
       
   406     {java_awt_event_KeyEvent_VK_COMPOSE, XK_Multi_key, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   407     {java_awt_event_KeyEvent_VK_ALT_GRAPH, XK_Mode_switch, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   408 
       
   409     /* Editing block */
       
   410     {java_awt_event_KeyEvent_VK_AGAIN, XK_Redo, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   411     {java_awt_event_KeyEvent_VK_AGAIN, XK_L2, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   412     {java_awt_event_KeyEvent_VK_UNDO, XK_Undo, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   413     {java_awt_event_KeyEvent_VK_UNDO, XK_L4, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   414     {java_awt_event_KeyEvent_VK_COPY, XK_L6, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   415     {java_awt_event_KeyEvent_VK_PASTE, XK_L8, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   416     {java_awt_event_KeyEvent_VK_CUT, XK_L10, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   417     {java_awt_event_KeyEvent_VK_FIND, XK_Find, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   418     {java_awt_event_KeyEvent_VK_FIND, XK_L9, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   419     {java_awt_event_KeyEvent_VK_PROPS, XK_L3, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   420     {java_awt_event_KeyEvent_VK_STOP, XK_L1, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   421 
       
   422     /* Sun vendor-specific versions for editing block */
       
   423     {java_awt_event_KeyEvent_VK_AGAIN, SunXK_Again, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   424     {java_awt_event_KeyEvent_VK_UNDO, SunXK_Undo, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   425     {java_awt_event_KeyEvent_VK_COPY, SunXK_Copy, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   426     {java_awt_event_KeyEvent_VK_PASTE, SunXK_Paste, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   427     {java_awt_event_KeyEvent_VK_CUT, SunXK_Cut, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   428     {java_awt_event_KeyEvent_VK_FIND, SunXK_Find, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   429     {java_awt_event_KeyEvent_VK_PROPS, SunXK_Props, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   430     {java_awt_event_KeyEvent_VK_STOP, SunXK_Stop, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   431 
       
   432     /* Apollo (HP) vendor-specific versions for editing block */
       
   433     {java_awt_event_KeyEvent_VK_COPY, apXK_Copy, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   434     {java_awt_event_KeyEvent_VK_CUT, apXK_Cut, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   435     {java_awt_event_KeyEvent_VK_PASTE, apXK_Paste, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   436 
       
   437     /* Other vendor-specific versions for editing block */
       
   438     {java_awt_event_KeyEvent_VK_COPY, osfXK_Copy, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   439     {java_awt_event_KeyEvent_VK_CUT, osfXK_Cut, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   440     {java_awt_event_KeyEvent_VK_PASTE, osfXK_Paste, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   441     {java_awt_event_KeyEvent_VK_UNDO, osfXK_Undo, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   442 
       
   443     /* Dead key mappings (for European keyboards) */
       
   444     {java_awt_event_KeyEvent_VK_DEAD_GRAVE, XK_dead_grave, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   445     {java_awt_event_KeyEvent_VK_DEAD_ACUTE, XK_dead_acute, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   446     {java_awt_event_KeyEvent_VK_DEAD_CIRCUMFLEX, XK_dead_circumflex, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   447     {java_awt_event_KeyEvent_VK_DEAD_TILDE, XK_dead_tilde, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   448     {java_awt_event_KeyEvent_VK_DEAD_MACRON, XK_dead_macron, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   449     {java_awt_event_KeyEvent_VK_DEAD_BREVE, XK_dead_breve, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   450     {java_awt_event_KeyEvent_VK_DEAD_ABOVEDOT, XK_dead_abovedot, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   451     {java_awt_event_KeyEvent_VK_DEAD_DIAERESIS, XK_dead_diaeresis, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   452     {java_awt_event_KeyEvent_VK_DEAD_ABOVERING, XK_dead_abovering, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   453     {java_awt_event_KeyEvent_VK_DEAD_DOUBLEACUTE, XK_dead_doubleacute, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   454     {java_awt_event_KeyEvent_VK_DEAD_CARON, XK_dead_caron, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   455     {java_awt_event_KeyEvent_VK_DEAD_CEDILLA, XK_dead_cedilla, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   456     {java_awt_event_KeyEvent_VK_DEAD_OGONEK, XK_dead_ogonek, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   457     {java_awt_event_KeyEvent_VK_DEAD_IOTA, XK_dead_iota, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   458     {java_awt_event_KeyEvent_VK_DEAD_VOICED_SOUND, XK_dead_voiced_sound, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   459     {java_awt_event_KeyEvent_VK_DEAD_SEMIVOICED_SOUND, XK_dead_semivoiced_sound, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   460 
       
   461     /* Sun vendor-specific dead key mappings (for European keyboards) */
       
   462     {java_awt_event_KeyEvent_VK_DEAD_GRAVE, SunXK_FA_Grave, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   463     {java_awt_event_KeyEvent_VK_DEAD_CIRCUMFLEX, SunXK_FA_Circum, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   464     {java_awt_event_KeyEvent_VK_DEAD_TILDE, SunXK_FA_Tilde, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   465     {java_awt_event_KeyEvent_VK_DEAD_ACUTE, SunXK_FA_Acute, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   466     {java_awt_event_KeyEvent_VK_DEAD_DIAERESIS, SunXK_FA_Diaeresis, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   467     {java_awt_event_KeyEvent_VK_DEAD_CEDILLA, SunXK_FA_Cedilla, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   468 
       
   469     /* DEC vendor-specific dead key mappings (for European keyboards) */
       
   470     {java_awt_event_KeyEvent_VK_DEAD_ABOVERING, DXK_ring_accent, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   471     {java_awt_event_KeyEvent_VK_DEAD_CIRCUMFLEX, DXK_circumflex_accent, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   472     {java_awt_event_KeyEvent_VK_DEAD_CEDILLA, DXK_cedilla_accent, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   473     {java_awt_event_KeyEvent_VK_DEAD_ACUTE, DXK_acute_accent, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   474     {java_awt_event_KeyEvent_VK_DEAD_GRAVE, DXK_grave_accent, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   475     {java_awt_event_KeyEvent_VK_DEAD_TILDE, DXK_tilde, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   476     {java_awt_event_KeyEvent_VK_DEAD_DIAERESIS, DXK_diaeresis, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   477 
       
   478     /* Other vendor-specific dead key mappings (for European keyboards) */
       
   479     {java_awt_event_KeyEvent_VK_DEAD_ACUTE, hpXK_mute_acute, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   480     {java_awt_event_KeyEvent_VK_DEAD_GRAVE, hpXK_mute_grave, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   481     {java_awt_event_KeyEvent_VK_DEAD_CIRCUMFLEX, hpXK_mute_asciicircum, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   482     {java_awt_event_KeyEvent_VK_DEAD_DIAERESIS, hpXK_mute_diaeresis, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   483     {java_awt_event_KeyEvent_VK_DEAD_TILDE, hpXK_mute_asciitilde, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
       
   484 
       
   485     {java_awt_event_KeyEvent_VK_UNDEFINED, NoSymbol, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN}
       
   486 };
       
   487 
       
   488 static Boolean
       
   489 keyboardHasKanaLockKey()
       
   490 {
       
   491     static Boolean haveResult = FALSE;
       
   492     static Boolean result = FALSE;
       
   493 
       
   494     int32_t minKeyCode, maxKeyCode, keySymsPerKeyCode;
       
   495     KeySym *keySyms, *keySymsStart, keySym;
       
   496     int32_t i;
       
   497     int32_t kanaCount = 0;
       
   498 
       
   499     // Solaris doesn't let you swap keyboards without rebooting,
       
   500     // so there's no need to check for the kana lock key more than once.
       
   501     if (haveResult) {
       
   502        return result;
       
   503     }
       
   504 
       
   505     // There's no direct way to determine whether the keyboard has
       
   506     // a kana lock key. From available keyboard mapping tables, it looks
       
   507     // like only keyboards with the kana lock key can produce keysyms
       
   508     // for kana characters. So, as an indirect test, we check for those.
       
   509 
       
   510     XDisplayKeycodes(awt_display, &minKeyCode, &maxKeyCode);
       
   511     keySyms = XGetKeyboardMapping(awt_display, minKeyCode, maxKeyCode - minKeyCode + 1, &keySymsPerKeyCode);
       
   512     keySymsStart = keySyms;
       
   513     for (i = 0; i < (maxKeyCode - minKeyCode + 1) * keySymsPerKeyCode; i++) {
       
   514         keySym = *keySyms++;
       
   515         if ((keySym & 0xff00) == 0x0400) {
       
   516             kanaCount++;
       
   517         }
       
   518     }
       
   519     XFree(keySymsStart);
       
   520 
       
   521     // use a (somewhat arbitrary) minimum so we don't get confused by a stray function key
       
   522     result = kanaCount > 10;
       
   523     haveResult = TRUE;
       
   524     return result;
       
   525 }
       
   526 
       
   527 void
       
   528 keysymToAWTKeyCode(KeySym x11Key, jint *keycode, Boolean *mapsToUnicodeChar,
       
   529   jint *keyLocation)
       
   530 {
       
   531     int32_t i;
       
   532 
       
   533     // Solaris uses XK_Mode_switch for both the non-locking AltGraph
       
   534     // and the locking Kana key, but we want to keep them separate for
       
   535     // KeyEvent.
       
   536     if (x11Key == XK_Mode_switch && keyboardHasKanaLockKey()) {
       
   537         *keycode = java_awt_event_KeyEvent_VK_KANA_LOCK;
       
   538         *mapsToUnicodeChar = FALSE;
       
   539         *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;
       
   540         return;
       
   541     }
       
   542 
       
   543     for (i = 0;
       
   544          keymapTable[i].awtKey != java_awt_event_KeyEvent_VK_UNDEFINED;
       
   545          i++) {
       
   546         if (keymapTable[i].x11Key == x11Key) {
       
   547             *keycode = keymapTable[i].awtKey;
       
   548             *mapsToUnicodeChar = keymapTable[i].mapsToUnicodeChar;
       
   549             *keyLocation = keymapTable[i].keyLocation;
       
   550             return;
       
   551         }
       
   552     }
       
   553 
       
   554     *keycode = java_awt_event_KeyEvent_VK_UNDEFINED;
       
   555     *mapsToUnicodeChar = FALSE;
       
   556     *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;
       
   557 
       
   558     DTRACE_PRINTLN1("keysymToAWTKeyCode: no key mapping found: keysym = %x", x11Key);
       
   559 }
       
   560 
       
   561 KeySym
       
   562 awt_getX11KeySym(jint awtKey)
       
   563 {
       
   564     int32_t i;
       
   565 
       
   566     if (awtKey == java_awt_event_KeyEvent_VK_KANA_LOCK && keyboardHasKanaLockKey()) {
       
   567         return XK_Mode_switch;
       
   568     }
       
   569 
       
   570     for (i = 0; keymapTable[i].awtKey != 0; i++) {
       
   571         if (keymapTable[i].awtKey == awtKey) {
       
   572             return keymapTable[i].x11Key;
       
   573         }
       
   574     }
       
   575 
       
   576     DTRACE_PRINTLN1("awt_getX11KeySym: no key mapping found: awtKey = %x", awtKey);
       
   577     return NoSymbol;
       
   578 }
       
   579 
       
   580 
       
   581 typedef struct COLLAPSE_INFO {
       
   582     Window win;
       
   583     DamageRect *r;
       
   584 } CollapseInfo;
       
   585 
       
   586 static void
       
   587 expandDamageRect(DamageRect * drect, XEvent * xev, Boolean debug, char *str)
       
   588 {
       
   589     int32_t x1 = xev->xexpose.x;
       
   590     int32_t y1 = xev->xexpose.y;
       
   591     int32_t x2 = x1 + xev->xexpose.width;
       
   592     int32_t y2 = y1 + xev->xexpose.height;
       
   593 
       
   594     /*
       
   595       if (debug) {
       
   596       printf("   %s: collapsing (%d,%d %dx%d) into (%d,%d %dx%d) ->>",
       
   597       str, x1, y1, xev->xexpose.width, xev->xexpose.height,
       
   598       drect->x1, drect->y1, drect->x2 - drect->x1, drect->y2 - drect->y1);
       
   599       }
       
   600     */
       
   601 
       
   602     drect->x1 = MIN(x1, drect->x1);
       
   603     drect->y1 = MIN(y1, drect->y1);
       
   604     drect->x2 = MAX(x2, drect->x2);
       
   605     drect->y2 = MAX(y2, drect->y2);
       
   606 
       
   607     /*
       
   608       if (debug) {
       
   609       printf("(%d,%d %dx%d) %s\n",
       
   610       drect->x1, drect->y1, drect->x2 - drect->x1, drect->y2 - drect->y1);
       
   611       }
       
   612     */
       
   613 
       
   614 }
       
   615 
       
   616 static Bool
       
   617 checkForExpose(Display * dpy, XEvent * evt, XPointer client_data)
       
   618 {
       
   619     CollapseInfo *cinfo = (CollapseInfo *) client_data;
       
   620 
       
   621     if ((evt->type == Expose && evt->xexpose.window == cinfo->win &&
       
   622          INTERSECTS(cinfo->r->x1, cinfo->r->x2, cinfo->r->y1, cinfo->r->y2,
       
   623                     evt->xexpose.x,
       
   624                     evt->xexpose.x + evt->xexpose.width,
       
   625                     evt->xexpose.y,
       
   626                     evt->xexpose.y + evt->xexpose.height)) ||
       
   627         (evt->type == GraphicsExpose && evt->xgraphicsexpose.drawable == cinfo->win &&
       
   628          INTERSECTS(cinfo->r->x1, cinfo->r->x2, cinfo->r->y1, cinfo->r->y2,
       
   629                     evt->xgraphicsexpose.x,
       
   630                     evt->xgraphicsexpose.x + evt->xgraphicsexpose.width,
       
   631                     evt->xgraphicsexpose.y,
       
   632                     evt->xgraphicsexpose.y + evt->xgraphicsexpose.height))) {
       
   633 
       
   634         return True;
       
   635     }
       
   636     return False;
       
   637 }
       
   638 
       
   639 /*
       
   640  * javaObject is an MComponentPeer instance
       
   641  */
       
   642 static void
       
   643 HandleExposeEvent(Widget w, jobject javaObject, XEvent * event)
       
   644 {
       
   645     jobject target;
       
   646     jint wdth, hght;
       
   647 
       
   648     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   649 
       
   650     switch (event->type) {
       
   651         case Expose:
       
   652         case GraphicsExpose:
       
   653         {
       
   654             struct ComponentData *cdata;
       
   655             Boolean debug = FALSE;
       
   656             jint drawState;
       
   657 
       
   658             /* Set the draw state */
       
   659             drawState = (*env)->GetIntField(env, javaObject,
       
   660                 mComponentPeerIDs.drawState);
       
   661             (*env)->SetIntField(env, javaObject, mComponentPeerIDs.drawState,
       
   662                 drawState | JAWT_LOCK_CLIP_CHANGED);
       
   663             cdata = (struct ComponentData *)
       
   664               JNU_GetLongFieldAsPtr(env, javaObject, mComponentPeerIDs.pData);
       
   665             if (JNU_IsNull(env, javaObject) || (cdata == NULL)) {
       
   666                 return;
       
   667             }
       
   668             if (event->xexpose.send_event) {
       
   669                 if (cdata->repaintPending & RepaintPending_REPAINT) {
       
   670                     cdata->repaintPending &= ~RepaintPending_REPAINT;
       
   671 
       
   672                     JNU_CallMethodByName(env,
       
   673                                          NULL,
       
   674                                          javaObject,
       
   675                                          "handleRepaint",
       
   676                                          "(IIII)V",
       
   677                                          (jint) cdata->repaintRect.x1,
       
   678                                          (jint) cdata->repaintRect.y1,
       
   679                                          (jint) cdata->repaintRect.x2
       
   680                                          - cdata->repaintRect.x1,
       
   681                                          (jint) cdata->repaintRect.y2
       
   682                                          - cdata->repaintRect.y1);
       
   683                     if ((*env)->ExceptionOccurred(env)) {
       
   684                         (*env)->ExceptionDescribe(env);
       
   685                         (*env)->ExceptionClear(env);
       
   686                     }
       
   687                 }
       
   688                 return;
       
   689             }
       
   690             if ((cdata->repaintPending & RepaintPending_EXPOSE) == 0) {
       
   691                 cdata->exposeRect.x1 = event->xexpose.x;
       
   692                 cdata->exposeRect.y1 = event->xexpose.y;
       
   693                 cdata->exposeRect.x2 = cdata->exposeRect.x1 + event->xexpose.width;
       
   694                 cdata->exposeRect.y2 = cdata->exposeRect.y1 + event->xexpose.height;
       
   695                 cdata->repaintPending |= RepaintPending_EXPOSE;
       
   696             } else {
       
   697                 expandDamageRect(&(cdata->exposeRect), event, debug, "1");
       
   698             }
       
   699 
       
   700             /* Only post Expose/Repaint if we know others arn't following
       
   701              * directly in the queue.
       
   702              */
       
   703             if (event->xexpose.count == 0) {
       
   704                 int32_t count = 0;
       
   705                 CollapseInfo cinfo;
       
   706 
       
   707                 cinfo.win = XtWindow(w);
       
   708                 cinfo.r = &(cdata->exposeRect);
       
   709 
       
   710                 /* Do a little more inspecting and collapse further if there
       
   711                  * are additional expose events pending on this window where
       
   712                  * the damage rects intersect with the current exposeRect.
       
   713                  */
       
   714                 while (TRUE) {
       
   715                     XEvent xev;
       
   716 
       
   717                     if (XCheckIfEvent(XtDisplay(w), &xev
       
   718                                       ,checkForExpose, (XtPointer) & cinfo)) {
       
   719                         count = xev.xexpose.count;
       
   720                         expandDamageRect(&(cdata->exposeRect), &xev, debug, "2");
       
   721 
       
   722                     } else {
       
   723                         /* XCheckIfEvent Failed. */
       
   724                         break;
       
   725                     }
       
   726                 }
       
   727 
       
   728                 cdata->repaintPending &= ~RepaintPending_EXPOSE;
       
   729 
       
   730                 /* Fix for bugtraq id 4262108. Paint events should not be
       
   731                  * delivered to components that have one of their
       
   732                  * dimensions equal to zero.
       
   733                  */
       
   734 
       
   735                 if ((*env)->EnsureLocalCapacity(env, 1) < 0) {
       
   736                     return;
       
   737                 }
       
   738 
       
   739                 target = (*env)->GetObjectField(env, javaObject,
       
   740                                                     mComponentPeerIDs.target);
       
   741                 wdth = (*env)->GetIntField(env, target, componentIDs.width);
       
   742                 hght = (*env)->GetIntField(env, target, componentIDs.height);
       
   743                 (*env)->DeleteLocalRef(env, target);
       
   744 
       
   745                 if ( wdth != 0 && hght != 0) {
       
   746                     JNU_CallMethodByName(env,
       
   747                                         NULL,
       
   748                                         javaObject,
       
   749                                         "handleExpose",
       
   750                                         "(IIII)V",
       
   751                                         (jint) cdata->exposeRect.x1,
       
   752                                         (jint) cdata->exposeRect.y1,
       
   753                                         (jint) cdata->exposeRect.x2
       
   754                                         - cdata->exposeRect.x1,
       
   755                                         (jint) cdata->exposeRect.y2
       
   756                                         - cdata->exposeRect.y1);
       
   757                     if ((*env)->ExceptionOccurred(env)) {
       
   758                         (*env)->ExceptionDescribe(env);
       
   759                         (*env)->ExceptionClear(env);
       
   760                     }
       
   761                 }
       
   762             }
       
   763         }
       
   764         break;
       
   765 
       
   766         default:
       
   767             jio_fprintf(stderr, "Got event %d in HandleExposeEvent!\n", event->type);
       
   768     }
       
   769 }
       
   770 
       
   771 /* We always store and return JNI GlobalRefs. */
       
   772 static jweak focusOwnerPeer = NULL;
       
   773 static jweak focusedWindowPeer = NULL;
       
   774 
       
   775 /*
       
   776  * This function should only be called under the
       
   777  * protection of AWT_LOCK(). Otherwise, multithreaded access
       
   778  * can corrupt the value of focusOwnerPeer variable.
       
   779  * This function returns LocalRef, result should be deleted
       
   780  * explicitly if called on a thread that never returns to
       
   781  * Java.
       
   782  */
       
   783 jobject
       
   784 awt_canvas_getFocusOwnerPeer() {
       
   785     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   786     jobject res;
       
   787     AWT_LOCK();
       
   788     res = (*env)->NewLocalRef(env, focusOwnerPeer);
       
   789     AWT_UNLOCK();
       
   790     return res;
       
   791 }
       
   792 
       
   793 /*
       
   794  * This function should only be called under the
       
   795  * protection of AWT_LOCK(). Otherwise, multithreaded access
       
   796  * can corrupt the value of focusedWindowPeer variable.
       
   797  * This function returns LocalRef, result should be deleted
       
   798  * explicitly if called on a thread that never returns to
       
   799  * Java.
       
   800  */
       
   801 jobject
       
   802 awt_canvas_getFocusedWindowPeer() {
       
   803     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   804     jobject res;
       
   805     AWT_LOCK();
       
   806     res = (*env)->NewLocalRef(env, focusedWindowPeer);
       
   807     AWT_UNLOCK();
       
   808     return res;
       
   809 }
       
   810 
       
   811 /*
       
   812  * Only call this function under AWT_LOCK(). Otherwise, multithreaded
       
   813  * access can corrupt the value of focusOwnerPeer variable.
       
   814  */
       
   815 void
       
   816 awt_canvas_setFocusOwnerPeer(jobject peer) {
       
   817     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   818     AWT_LOCK();
       
   819     if (focusOwnerPeer != NULL) {
       
   820         (*env)->DeleteWeakGlobalRef(env, focusOwnerPeer);
       
   821     }
       
   822     focusOwnerPeer = (peer != NULL)
       
   823         ? (*env)->NewWeakGlobalRef(env, peer) : NULL;
       
   824     AWT_UNLOCK();
       
   825 }
       
   826 
       
   827 /*
       
   828  * Only call this function under AWT_LOCK(). Otherwise, multithreaded
       
   829  * access can corrupt the value of focusedWindowPeer variable.
       
   830  */
       
   831 void
       
   832 awt_canvas_setFocusedWindowPeer(jobject peer) {
       
   833     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   834     AWT_LOCK();
       
   835     if (focusedWindowPeer != NULL) {
       
   836         (*env)->DeleteWeakGlobalRef(env, focusedWindowPeer);
       
   837     }
       
   838     focusedWindowPeer = (peer != NULL)
       
   839         ? (*env)->NewWeakGlobalRef(env, peer) : NULL;
       
   840     AWT_UNLOCK();
       
   841 }
       
   842 
       
   843 void callFocusCallback(jobject focusPeer, int focus_type, jobject cause) {
       
   844     awt_post_java_focus_event(focusPeer,
       
   845                               focus_type,
       
   846                               cause,
       
   847                               NULL);
       
   848     awt_canvas_setFocusOwnerPeer(focusPeer);
       
   849 }
       
   850 
       
   851 
       
   852 void
       
   853 handleFocusEvent(Widget w,
       
   854                  XFocusChangeEvent * fevent,
       
   855                  XtPointer client_data,
       
   856                  Boolean * cont,
       
   857                  Boolean passEvent,
       
   858                  jobject cause)
       
   859 {
       
   860     if (fevent->type == FocusIn) {
       
   861         if (fevent->mode == NotifyNormal &&
       
   862             fevent->detail != NotifyPointer && fevent->detail != NotifyVirtual)
       
   863         {
       
   864 #ifdef DEBUG_FOCUS
       
   865             printf("window = %d, mode = %d, detail = %d\n", fevent->window, fevent->mode, fevent->detail);
       
   866             printf("----posting java FOCUS GAINED on window %d, pass = %d\n", XtWindow(w), passEvent);
       
   867 #endif
       
   868             awt_post_java_focus_event(client_data,
       
   869                                       java_awt_event_FocusEvent_FOCUS_GAINED,
       
   870                                       cause,
       
   871                                       NULL);
       
   872             awt_canvas_setFocusOwnerPeer(client_data);
       
   873         }
       
   874     } else {
       
   875         /* FocusOut */
       
   876         if (fevent->mode == NotifyNormal &&
       
   877             fevent->detail != NotifyPointer && fevent->detail != NotifyVirtual)
       
   878         {
       
   879 #ifdef DEBUG_FOCUS
       
   880           printf("window = %d, mode = %d, detail = %d\n", fevent->window, fevent->mode, fevent->detail);
       
   881           printf("----posting java FOCUS LOST on window %d, pass = %d, temp = %d\n", XtWindow(w), passEvent, temp);
       
   882 #endif
       
   883             awt_post_java_focus_event(client_data,
       
   884                                       java_awt_event_FocusEvent_FOCUS_LOST,
       
   885                                       cause,
       
   886                                       NULL);
       
   887             awt_canvas_setFocusOwnerPeer(NULL);
       
   888         }
       
   889     }
       
   890     *cont = TRUE;
       
   891 }
       
   892 
       
   893 void callFocusHandler(Widget w, int eventType, jobject cause) {
       
   894     jobject peer = NULL;
       
   895     XFocusChangeEvent event;
       
   896     Boolean cont;
       
   897     JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   898 
       
   899     if (w == NULL) {
       
   900         return;
       
   901     }
       
   902 
       
   903     peer = findPeer(&w);
       
   904     if (peer == NULL) {
       
   905         w = findTopLevelByShell(w);
       
   906         if (w != NULL) {
       
   907             peer = findPeer(&w);
       
   908         }
       
   909     }
       
   910     if (peer == NULL) {
       
   911         return;
       
   912     }
       
   913     memset(&event, 0, sizeof(event));
       
   914     event.type = eventType;
       
   915     event.mode = NotifyNormal;
       
   916     event.detail = NotifyAncestor;
       
   917     event.window = XtWindow(w);
       
   918     cont = FALSE;
       
   919     handleFocusEvent(w, &event, (XtPointer)peer, &cont, TRUE, cause);
       
   920 }
       
   921 
       
   922 /**
       
   923  * Copy XEvent to jbyteArray and save it in AWTEvent
       
   924  */
       
   925 void
       
   926 awt_copyXEventToAWTEvent(JNIEnv *env, XEvent * xev, jobject jevent)
       
   927 {
       
   928     jbyteArray bdata;
       
   929     if (xev != NULL) {
       
   930         if ((*env)->EnsureLocalCapacity(env, 1) < 0) {
       
   931             return;
       
   932         }
       
   933         bdata = (*env)->NewByteArray(env, sizeof(XEvent));
       
   934         if (bdata != NULL) {
       
   935             (*env)->SetByteArrayRegion(env, bdata, 0, sizeof(XEvent),
       
   936                                        (jbyte *)xev);
       
   937             (*env)->SetObjectField(env, jevent, awtEventIDs.bdata, bdata);
       
   938             (*env)->DeleteLocalRef(env, bdata);
       
   939         }
       
   940     }
       
   941 }
       
   942 
       
   943 /* Returns new modifiers set like ???_DOWN_MASK for keyboard and mouse after the event.
       
   944  * The modifiers on a Java key event reflect the state of the modifier keys
       
   945  * immediately AFTER the key press or release.  This usually doesn't require
       
   946  * us to change the modifiers: the exception is when the key pressed or
       
   947  * released is a modifier key.  Since the state of an XEvent represents
       
   948  * the modifiers BEFORE the event, we change the modifiers according to
       
   949  * the button and keycode.
       
   950  */
       
   951 jint
       
   952 getModifiers(uint32_t state, jint button, jint keyCode)
       
   953 {
       
   954     jint modifiers = 0;
       
   955 
       
   956     if (((state & ShiftMask) != 0) ^ (keyCode == java_awt_event_KeyEvent_VK_SHIFT))
       
   957     {
       
   958         modifiers |= java_awt_event_InputEvent_SHIFT_DOWN_MASK;
       
   959     }
       
   960     if (((state & ControlMask) != 0) ^ (keyCode == java_awt_event_KeyEvent_VK_CONTROL))
       
   961     {
       
   962         modifiers |= java_awt_event_InputEvent_CTRL_DOWN_MASK;
       
   963     }
       
   964     if (((state & awt_MetaMask) != 0) ^ (keyCode == java_awt_event_KeyEvent_VK_META))
       
   965     {
       
   966         modifiers |= java_awt_event_InputEvent_META_DOWN_MASK;
       
   967     }
       
   968     if (((state & awt_AltMask) != 0) ^ (keyCode == java_awt_event_KeyEvent_VK_ALT))
       
   969     {
       
   970         modifiers |= java_awt_event_InputEvent_ALT_DOWN_MASK;
       
   971     }
       
   972     if (((state & awt_ModeSwitchMask) != 0) ^ (keyCode == java_awt_event_KeyEvent_VK_ALT_GRAPH))
       
   973     {
       
   974         modifiers |= java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK;
       
   975     }
       
   976     if (((state & Button1Mask) != 0) ^ (button == java_awt_event_MouseEvent_BUTTON1)) {
       
   977         modifiers |= java_awt_event_InputEvent_BUTTON1_DOWN_MASK;
       
   978     }
       
   979     if (((state & Button2Mask) != 0) ^ (button == java_awt_event_MouseEvent_BUTTON2)) {
       
   980         modifiers |= java_awt_event_InputEvent_BUTTON2_DOWN_MASK;
       
   981     }
       
   982     if (((state & Button3Mask) != 0) ^ (button == java_awt_event_MouseEvent_BUTTON3)) {
       
   983         modifiers |= java_awt_event_InputEvent_BUTTON3_DOWN_MASK;
       
   984     }
       
   985     return modifiers;
       
   986 }
       
   987 
       
   988 /* Returns which mouse button has changed state
       
   989  */
       
   990 jint
       
   991 getButton(uint32_t button)
       
   992 {
       
   993     switch (button) {
       
   994     case Button1:
       
   995         return java_awt_event_MouseEvent_BUTTON1;
       
   996     case Button2:
       
   997         return java_awt_event_MouseEvent_BUTTON2;
       
   998     case Button3:
       
   999         return java_awt_event_MouseEvent_BUTTON3;
       
  1000     }
       
  1001     return java_awt_event_MouseEvent_NOBUTTON;
       
  1002 }
       
  1003 
       
  1004 
       
  1005 /* This function changes the state of the native XEvent AFTER
       
  1006  * the corresponding Java event has been processed.  The XEvent
       
  1007  * needs to be modified before it is dispatched to the native widget.
       
  1008  */
       
  1009 void
       
  1010 awt_modify_KeyEvent(JNIEnv *env, XEvent *xevent, jobject jevent)
       
  1011 {
       
  1012     jint keyCode;
       
  1013     jchar keyChar;
       
  1014     jint modifiers;
       
  1015     KeySym keysym = (KeySym) java_awt_event_KeyEvent_CHAR_UNDEFINED;
       
  1016 
       
  1017     if (xevent->type != KeyPress && xevent->type != KeyRelease) {
       
  1018         return;
       
  1019     }
       
  1020 
       
  1021     keyCode = (*env)->GetIntField(env, jevent, keyEventIDs.keyCode);
       
  1022     keyChar = (*env)->GetCharField(env, jevent, keyEventIDs.keyChar);
       
  1023     modifiers = (*env)->GetIntField(env, jevent, inputEventIDs.modifiers);
       
  1024 
       
  1025     switch (keyCode) {
       
  1026         case java_awt_event_KeyEvent_VK_MULTIPLY:
       
  1027         case java_awt_event_KeyEvent_VK_SUBTRACT:
       
  1028         case java_awt_event_KeyEvent_VK_DIVIDE:
       
  1029             /* Bugid 4103229:  Change the X event so these three Numpad
       
  1030              * keys work with the NumLock off.  For some reason, Motif
       
  1031              * widgets ignore the events produced by these three keys
       
  1032              * unless the NumLock is on.  It also ignores them if some
       
  1033              * other modifiers are set.  Turn off ALL modifiers, then
       
  1034              * turn NumLock mask on in the X event.
       
  1035              */
       
  1036             xevent->xkey.state = awt_NumLockMask;
       
  1037             return;
       
  1038         case java_awt_event_KeyEvent_VK_ENTER:
       
  1039         case java_awt_event_KeyEvent_VK_BACK_SPACE:
       
  1040         case java_awt_event_KeyEvent_VK_TAB:
       
  1041         case java_awt_event_KeyEvent_VK_ESCAPE:
       
  1042         case java_awt_event_KeyEvent_VK_ADD:
       
  1043         case java_awt_event_KeyEvent_VK_DECIMAL:
       
  1044         case java_awt_event_KeyEvent_VK_NUMPAD0:
       
  1045         case java_awt_event_KeyEvent_VK_NUMPAD1:
       
  1046         case java_awt_event_KeyEvent_VK_NUMPAD2:
       
  1047         case java_awt_event_KeyEvent_VK_NUMPAD3:
       
  1048         case java_awt_event_KeyEvent_VK_NUMPAD4:
       
  1049         case java_awt_event_KeyEvent_VK_NUMPAD5:
       
  1050         case java_awt_event_KeyEvent_VK_NUMPAD6:
       
  1051         case java_awt_event_KeyEvent_VK_NUMPAD7:
       
  1052         case java_awt_event_KeyEvent_VK_NUMPAD8:
       
  1053         case java_awt_event_KeyEvent_VK_NUMPAD9:
       
  1054             keysym = awt_getX11KeySym(keyCode);
       
  1055             break;
       
  1056         case java_awt_event_KeyEvent_VK_DELETE:
       
  1057             /* For some reason XKeysymToKeycode returns incorrect value for
       
  1058              * Delete, so we don't want to modify the original event
       
  1059              */
       
  1060             break;
       
  1061         default:
       
  1062             if (keyChar < (KeySym) 256) {
       
  1063                 keysym = (KeySym) keyChar;
       
  1064             } else {
       
  1065                 keysym = awt_getX11KeySym(keyCode);
       
  1066             }
       
  1067             break;
       
  1068     }
       
  1069 
       
  1070     if (keysym < (KeySym) 256) {
       
  1071         if (modifiers & java_awt_event_InputEvent_CTRL_MASK) {
       
  1072             switch (keysym + 64) {
       
  1073                 case '[':
       
  1074                 case ']':
       
  1075                 case '\\':
       
  1076                 case '_':
       
  1077                     keysym += 64;
       
  1078                     break;
       
  1079                 default:
       
  1080                     if (isalpha((int32_t)(keysym + 'a' - 1))) {
       
  1081                         keysym += ('a' - 1);
       
  1082                     }
       
  1083                     break;
       
  1084             }
       
  1085         }
       
  1086         /*
       
  1087          * 0xff61 is Unicode value of first XK_kana_fullstop.
       
  1088          * We need X Keysym to Unicode map in post1.1 release
       
  1089          * to support more international keyboards.
       
  1090          */
       
  1091         if (keysym >= (KeySym) 0xff61 && keysym <= (KeySym) 0xff9f) {
       
  1092             keysym = keysym - 0xff61 + XK_kana_fullstop;
       
  1093         }
       
  1094         xevent->xkey.keycode = XKeysymToKeycode(awt_display, keysym);
       
  1095     }
       
  1096 
       
  1097     if (keysym >= 'A' && keysym <= 'Z') {
       
  1098         xevent->xkey.state |= ShiftMask;
       
  1099     }
       
  1100     if (modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) {
       
  1101         xevent->xkey.state |= ShiftMask;
       
  1102     }
       
  1103     if (modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK) {
       
  1104         xevent->xkey.state |= ControlMask;
       
  1105     }
       
  1106     if (modifiers & java_awt_event_InputEvent_META_DOWN_MASK) {
       
  1107         xevent->xkey.state |= awt_MetaMask;
       
  1108     }
       
  1109     if (modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) {
       
  1110         xevent->xkey.state |= awt_AltMask;
       
  1111     }
       
  1112     if (modifiers & java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK) {
       
  1113         xevent->xkey.state |= awt_ModeSwitchMask;
       
  1114     }
       
  1115     if (modifiers & java_awt_event_InputEvent_BUTTON1_DOWN_MASK) {
       
  1116         xevent->xkey.state |= Button1Mask;
       
  1117     }
       
  1118     if (modifiers & java_awt_event_InputEvent_BUTTON2_DOWN_MASK) {
       
  1119         xevent->xkey.state |= Button2Mask;
       
  1120     }
       
  1121     if (modifiers & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) {
       
  1122         xevent->xkey.state |= Button3Mask;
       
  1123     }
       
  1124 }
       
  1125 
       
  1126 
       
  1127 /* Called from handleKeyEvent.  The purpose of this function is
       
  1128  * to check for a list of vendor-specific keysyms, most of which
       
  1129  * have values greater than 0xFFFF.  Most of these keys don't map
       
  1130  * to unicode characters, but some do.
       
  1131  *
       
  1132  * For keys that don't map to unicode characters, the keysym
       
  1133  * is irrelevant at this point.  We set the keysym to zero
       
  1134  * to ensure that the switch statement immediately below
       
  1135  * this function call (in adjustKeySym) won't incorrectly act
       
  1136  * on them after the high bits are stripped off.
       
  1137  *
       
  1138  * For keys that do map to unicode characters, we change the keysym
       
  1139  * to the equivalent that is < 0xFFFF
       
  1140  */
       
  1141 static void
       
  1142 handleVendorKeySyms(XEvent *event, KeySym *keysym)
       
  1143 {
       
  1144     KeySym originalKeysym = *keysym;
       
  1145 
       
  1146     switch (*keysym) {
       
  1147         /* Apollo (HP) vendor-specific from <X11/ap_keysym.h> */
       
  1148         case apXK_Copy:
       
  1149         case apXK_Cut:
       
  1150         case apXK_Paste:
       
  1151         /* DEC vendor-specific from <X11/DECkeysym.h> */
       
  1152         case DXK_ring_accent:         /* syn usldead_ring */
       
  1153         case DXK_circumflex_accent:
       
  1154         case DXK_cedilla_accent:      /* syn usldead_cedilla */
       
  1155         case DXK_acute_accent:
       
  1156         case DXK_grave_accent:
       
  1157         case DXK_tilde:
       
  1158         case DXK_diaeresis:
       
  1159         /* Sun vendor-specific from <X11/Sunkeysym.h> */
       
  1160         case SunXK_FA_Grave:
       
  1161         case SunXK_FA_Circum:
       
  1162         case SunXK_FA_Tilde:
       
  1163         case SunXK_FA_Acute:
       
  1164         case SunXK_FA_Diaeresis:
       
  1165         case SunXK_FA_Cedilla:
       
  1166         case SunXK_F36:                /* Labeled F11 */
       
  1167         case SunXK_F37:                /* Labeled F12 */
       
  1168         case SunXK_Props:
       
  1169         case SunXK_Copy:
       
  1170         case SunXK_Open:
       
  1171         case SunXK_Paste:
       
  1172         case SunXK_Cut:
       
  1173         /* Other vendor-specific from HPkeysym.h */
       
  1174         case hpXK_mute_acute:          /* syn usldead_acute */
       
  1175         case hpXK_mute_grave:          /* syn usldead_grave */
       
  1176         case hpXK_mute_asciicircum:    /* syn usldead_asciicircum */
       
  1177         case hpXK_mute_diaeresis:      /* syn usldead_diaeresis */
       
  1178         case hpXK_mute_asciitilde:     /* syn usldead_asciitilde */
       
  1179         case osfXK_Copy:
       
  1180         case osfXK_Cut:
       
  1181         case osfXK_Paste:
       
  1182         case osfXK_PageUp:
       
  1183         case osfXK_PageDown:
       
  1184         case osfXK_EndLine:
       
  1185         case osfXK_Clear:
       
  1186         case osfXK_Left:
       
  1187         case osfXK_Up:
       
  1188         case osfXK_Right:
       
  1189         case osfXK_Down:
       
  1190         case osfXK_Prior:
       
  1191         case osfXK_Next:
       
  1192         case osfXK_Insert:
       
  1193         case osfXK_Undo:
       
  1194         case osfXK_Help:
       
  1195             *keysym = 0;
       
  1196             break;
       
  1197         /*
       
  1198          * The rest DO map to unicode characters, so translate them
       
  1199          */
       
  1200         case osfXK_BackSpace:
       
  1201             *keysym = XK_BackSpace;
       
  1202             break;
       
  1203         case osfXK_Escape:
       
  1204             *keysym = XK_Escape;
       
  1205             break;
       
  1206         case osfXK_Cancel:
       
  1207             *keysym = XK_Cancel;
       
  1208             break;
       
  1209         case osfXK_Delete:
       
  1210             *keysym = XK_Delete;
       
  1211             break;
       
  1212         default:
       
  1213             break;
       
  1214     }
       
  1215 
       
  1216     if (originalKeysym != *keysym) {
       
  1217         DTRACE_PRINTLN2("In handleVendorKeySyms: originalKeysym=%x, keysym=%x",
       
  1218           originalKeysym, *keysym);
       
  1219     }
       
  1220 }
       
  1221 
       
  1222 /* Called from handleKeyEvent.
       
  1223  * The purpose of this function is to adjust the keysym and XEvent
       
  1224  * keycode for a key event.  This is basically a conglomeration of
       
  1225  * bugfixes that require these adjustments.
       
  1226  */
       
  1227 static void
       
  1228 adjustKeySym(XEvent *event, KeySym *keysym)
       
  1229 {
       
  1230     KeySym originalKeysym = *keysym;
       
  1231 
       
  1232     /* We have seen bits set in the high two bytes on Linux,
       
  1233      * which prevents this switch statement from executing
       
  1234      * correctly.  Strip off the high order bits.
       
  1235      */
       
  1236     *keysym &= 0x0000FFFF;
       
  1237 
       
  1238     switch (*keysym) {
       
  1239         case XK_Return:
       
  1240             *keysym = XK_Linefeed;     /* fall thru */
       
  1241         case XK_BackSpace:
       
  1242         case XK_Tab:
       
  1243         case XK_Linefeed:
       
  1244         case XK_Escape:
       
  1245         case XK_Delete:
       
  1246             /* strip off highorder bits defined in keysymdef.h
       
  1247              * I think doing this converts them to values that
       
  1248              * we can cast to jchars and use as java keychars.
       
  1249              * If so, it's really a hack.
       
  1250              */
       
  1251             *keysym &= 0x007F;
       
  1252             break;
       
  1253         case XK_Cancel:
       
  1254             *keysym = 0x0018;  /* the unicode char for Cancel */
       
  1255             break;
       
  1256         case XK_KP_Decimal:
       
  1257             *keysym = '.';
       
  1258             break;
       
  1259         case XK_KP_Add:
       
  1260             *keysym = '+';
       
  1261             break;
       
  1262         case XK_F24:           /* NumLock off */
       
  1263         case XK_KP_Subtract:   /* NumLock on */
       
  1264             *keysym = '-';
       
  1265             break;
       
  1266         case XK_F25:           /* NumLock off */
       
  1267         case XK_KP_Divide:     /* NumLock on */
       
  1268             *keysym = '/';
       
  1269             break;
       
  1270         case XK_F26:           /* NumLock off */
       
  1271         case XK_KP_Multiply:   /* NumLock on */
       
  1272             *keysym = '*';
       
  1273             break;
       
  1274         case XK_KP_Equal:
       
  1275             *keysym = '=';
       
  1276             break;
       
  1277         case XK_KP_0:
       
  1278             *keysym = '0';
       
  1279             break;
       
  1280         case XK_KP_1:
       
  1281             *keysym = '1';
       
  1282             break;
       
  1283         case XK_KP_2:
       
  1284             *keysym = '2';
       
  1285             break;
       
  1286         case XK_KP_3:
       
  1287             *keysym = '3';
       
  1288             break;
       
  1289         case XK_KP_4:
       
  1290             *keysym = '4';
       
  1291             break;
       
  1292         case XK_KP_5:
       
  1293             *keysym = '5';
       
  1294             break;
       
  1295         case XK_KP_6:
       
  1296             *keysym = '6';
       
  1297             break;
       
  1298         case XK_KP_7:
       
  1299             *keysym = '7';
       
  1300             break;
       
  1301         case XK_KP_8:
       
  1302             *keysym = '8';
       
  1303             break;
       
  1304         case XK_KP_9:
       
  1305             *keysym = '9';
       
  1306             break;
       
  1307         case XK_KP_Left:  /* Bug 4350175 */
       
  1308             *keysym = XK_Left;
       
  1309             event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym);
       
  1310             break;
       
  1311         case XK_KP_Up:
       
  1312             *keysym = XK_Up;
       
  1313             event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym);
       
  1314             break;
       
  1315         case XK_KP_Right:
       
  1316             *keysym = XK_Right;
       
  1317             event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym);
       
  1318             break;
       
  1319         case XK_KP_Down:
       
  1320             *keysym = XK_Down;
       
  1321             event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym);
       
  1322             break;
       
  1323         case XK_KP_Home:
       
  1324             *keysym = XK_Home;
       
  1325             event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym);
       
  1326             break;
       
  1327         case XK_KP_End:
       
  1328             *keysym = XK_End;
       
  1329             event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym);
       
  1330             break;
       
  1331         case XK_KP_Page_Up:
       
  1332             *keysym = XK_Page_Up;
       
  1333             event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym);
       
  1334             break;
       
  1335         case XK_KP_Page_Down:
       
  1336             *keysym = XK_Page_Down;
       
  1337             event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym);
       
  1338             break;
       
  1339         case XK_KP_Begin:
       
  1340             *keysym = XK_Begin;
       
  1341             event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym);
       
  1342             break;
       
  1343         case XK_KP_Insert:
       
  1344             *keysym = XK_Insert;
       
  1345             event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym);
       
  1346             break;
       
  1347         case XK_KP_Delete:
       
  1348             *keysym = XK_Delete;
       
  1349             event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym);
       
  1350             *keysym &= 0x007F;
       
  1351             break;
       
  1352         case XK_KP_Enter:
       
  1353             *keysym = XK_Linefeed;
       
  1354             event->xkey.keycode = XKeysymToKeycode(awt_display, XK_Return);
       
  1355             *keysym &= 0x007F;
       
  1356             break;
       
  1357         default:
       
  1358             break;
       
  1359     }
       
  1360 
       
  1361     if (originalKeysym != *keysym) {
       
  1362         DTRACE_PRINTLN2("In adjustKeySym: originalKeysym=%x, keysym=%x",
       
  1363           originalKeysym, *keysym);
       
  1364     }
       
  1365 }
       
  1366 
       
  1367 /*
       
  1368  * What a sniffer sez?
       
  1369  * Xsun and Xorg if NumLock is on do two thing different:
       
  1370  * keep Keypad key in different places of keysyms array and
       
  1371  * ignore/obey "ModLock is ShiftLock", so we should choose.
       
  1372  * People say, it's right to use behavior and not Vendor tags to decide.
       
  1373  * Maybe. But why these tags were invented, then?
       
  1374  * TODO: use behavior, not tags. Maybe.
       
  1375  */
       
  1376 static Boolean
       
  1377 isXsunServer(XEvent *event) {
       
  1378     if( awt_ServerDetected ) return awt_IsXsun;
       
  1379     if( strncmp( ServerVendor( event->xkey.display ), "Sun Microsystems, Inc.", 32) ) {
       
  1380         awt_ServerDetected = True;
       
  1381         awt_IsXsun = False;
       
  1382         return False;
       
  1383     }
       
  1384     // Now, it's Sun. It still may be Xorg though, eg on Solaris 10, x86.
       
  1385     // Today (2005), VendorRelease of Xorg is a Big Number unlike Xsun.
       
  1386     if( VendorRelease( event->xkey.display ) > 10000 ) {
       
  1387         awt_ServerDetected = True;
       
  1388         awt_IsXsun = False;
       
  1389         return False;
       
  1390     }
       
  1391     awt_ServerDetected = True;
       
  1392     awt_IsXsun = True;
       
  1393     return True;
       
  1394 }
       
  1395 static Boolean
       
  1396 isKPevent(XEvent *event)
       
  1397 {
       
  1398     /*
       
  1399        Xlib manual, ch 12.7 says, as a first rule for choice of keysym:
       
  1400        The numlock modifier is on and the second KeySym is a keypad KeySym. In this case,
       
  1401        if the Shift modifier is on, or if the Lock modifier is on and is interpreted as ShiftLock,
       
  1402        then the first KeySym is used, otherwise the second KeySym is used.
       
  1403 
       
  1404        However, Xsun server does ignore ShiftLock and always takes 3-rd element from an array.
       
  1405 
       
  1406        So, is it a keypad keysym?
       
  1407      */
       
  1408     jint mods = getModifiers(event->xkey.state, 0, event->xkey.keycode);
       
  1409     Boolean bsun = isXsunServer( event );
       
  1410 
       
  1411     return IsKeypadKey( XKeycodeToKeysym(event->xkey.display, event->xkey.keycode,(bsun && !awt_UseXKB ? 2 : 1) ) );
       
  1412 }
       
  1413 /*
       
  1414  * In a next redesign, get rid of this code altogether.
       
  1415  *
       
  1416  */
       
  1417 static void
       
  1418 handleKeyEventWithNumLockMask_New(XEvent *event, KeySym *keysym)
       
  1419 {
       
  1420     KeySym originalKeysym = *keysym;
       
  1421     if( !isKPevent( event ) ) {
       
  1422         return;
       
  1423     }
       
  1424     if( isXsunServer( event ) && !awt_UseXKB ) {
       
  1425         if( (event->xkey.state & ShiftMask) ) { // shift modifier is on
       
  1426             *keysym = XKeycodeToKeysym(event->xkey.display,
       
  1427                                    event->xkey.keycode, 3);
       
  1428          }else {
       
  1429             *keysym = XKeycodeToKeysym(event->xkey.display,
       
  1430                                    event->xkey.keycode, 2);
       
  1431          }
       
  1432     } else {
       
  1433         if( (event->xkey.state & ShiftMask) || // shift modifier is on
       
  1434             ((event->xkey.state & LockMask) && // lock modifier is on
       
  1435              (awt_ModLockIsShiftLock)) ) {     // it is interpreted as ShiftLock
       
  1436             *keysym = XKeycodeToKeysym(event->xkey.display,
       
  1437                                    event->xkey.keycode, 0);
       
  1438         }else{
       
  1439             *keysym = XKeycodeToKeysym(event->xkey.display,
       
  1440                                    event->xkey.keycode, 1);
       
  1441         }
       
  1442     }
       
  1443 }
       
  1444 
       
  1445 /* Called from handleKeyEvent.
       
  1446  * The purpose of this function is to make some adjustments to keysyms
       
  1447  * that have been found to be necessary when the NumLock mask is set.
       
  1448  * They come from various bug fixes and rearchitectures.
       
  1449  * This function is meant to be called when
       
  1450  * (event->xkey.state & awt_NumLockMask) is TRUE.
       
  1451  */
       
  1452 static void
       
  1453 handleKeyEventWithNumLockMask(XEvent *event, KeySym *keysym)
       
  1454 {
       
  1455     KeySym originalKeysym = *keysym;
       
  1456 
       
  1457 #ifndef __linux__
       
  1458     /* The following code on Linux will cause the keypad keys
       
  1459      * not to echo on JTextField when the NumLock is on. The
       
  1460      * keysyms will be 0, because the last parameter 2 is not defined.
       
  1461      * See Xlib Programming Manual, O'Reilly & Associates, Section
       
  1462      * 9.1.5 "Other Keyboard-handling Routines", "The meaning of
       
  1463      * the keysym list beyond the first two (unmodified, Shift or
       
  1464      * Shift Lock) is not defined."
       
  1465      */
       
  1466 
       
  1467     /* Translate again with NumLock as modifier. */
       
  1468     /* ECH - I wonder why we think that NumLock corresponds to 2?
       
  1469      * On Linux, we've seen xmodmap -pm yield mod2 as NumLock,
       
  1470      * but I don't know that it will be for every configuration.
       
  1471      * Perhaps using the index (modn in awt_MToolkit.c:setup_modifier_map)
       
  1472      * would be more correct.
       
  1473      */
       
  1474     *keysym = XKeycodeToKeysym(event->xkey.display,
       
  1475                                event->xkey.keycode, 2);
       
  1476     if (originalKeysym != *keysym) {
       
  1477         DTRACE_PRINTLN3("%s=%x, keysym=%x",
       
  1478           "In handleKeyEventWithNumLockMask ifndef linux: originalKeysym",
       
  1479           originalKeysym, *keysym);
       
  1480     }
       
  1481 #endif
       
  1482 
       
  1483     /* Note: the XK_R? key assignments are for Type 4 kbds */
       
  1484     switch (*keysym) {
       
  1485         case XK_R13:
       
  1486             *keysym = XK_KP_1;
       
  1487             break;
       
  1488         case XK_R14:
       
  1489             *keysym = XK_KP_2;
       
  1490             break;
       
  1491         case XK_R15:
       
  1492             *keysym = XK_KP_3;
       
  1493             break;
       
  1494         case XK_R10:
       
  1495             *keysym = XK_KP_4;
       
  1496             break;
       
  1497         case XK_R11:
       
  1498             *keysym = XK_KP_5;
       
  1499             break;
       
  1500         case XK_R12:
       
  1501             *keysym = XK_KP_6;
       
  1502             break;
       
  1503         case XK_R7:
       
  1504             *keysym = XK_KP_7;
       
  1505             break;
       
  1506         case XK_R8:
       
  1507             *keysym = XK_KP_8;
       
  1508             break;
       
  1509         case XK_R9:
       
  1510             *keysym = XK_KP_9;
       
  1511             break;
       
  1512         case XK_KP_Insert:
       
  1513             *keysym = XK_KP_0;
       
  1514             break;
       
  1515         case XK_KP_Delete:
       
  1516             *keysym = XK_KP_Decimal;
       
  1517             break;
       
  1518         case XK_R4:
       
  1519             *keysym = XK_KP_Equal;  /* Type 4 kbd */
       
  1520             break;
       
  1521         case XK_R5:
       
  1522             *keysym = XK_KP_Divide;
       
  1523             break;
       
  1524         case XK_R6:
       
  1525             *keysym = XK_KP_Multiply;
       
  1526             break;
       
  1527         /*
       
  1528          * Need the following keysym changes for Linux key releases.
       
  1529          * Sometimes the modifier state gets messed up, so we get a
       
  1530          * KP_Left when we should get a KP_4, for example.
       
  1531          * XK_KP_Insert and XK_KP_Delete were already handled above.
       
  1532          */
       
  1533         case XK_KP_Left:
       
  1534             *keysym = XK_KP_4;
       
  1535             break;
       
  1536         case XK_KP_Up:
       
  1537             *keysym = XK_KP_8;
       
  1538             break;
       
  1539         case XK_KP_Right:
       
  1540             *keysym = XK_KP_6;
       
  1541             break;
       
  1542         case XK_KP_Down:
       
  1543             *keysym = XK_KP_2;
       
  1544             break;
       
  1545         case XK_KP_Home:
       
  1546             *keysym = XK_KP_7;
       
  1547             break;
       
  1548         case XK_KP_End:
       
  1549             *keysym = XK_KP_1;
       
  1550             break;
       
  1551         case XK_KP_Page_Up:
       
  1552             *keysym = XK_KP_9;
       
  1553             break;
       
  1554         case XK_KP_Page_Down:
       
  1555             *keysym = XK_KP_3;
       
  1556             break;
       
  1557         case XK_KP_Begin:
       
  1558             *keysym = XK_KP_5;
       
  1559             break;
       
  1560         default:
       
  1561             break;
       
  1562     }
       
  1563 
       
  1564     if (originalKeysym != *keysym) {
       
  1565         DTRACE_PRINTLN2("In handleKeyEventWithNumLockMask: originalKeysym=%x, keysym=%x",
       
  1566           originalKeysym, *keysym);
       
  1567     }
       
  1568 }
       
  1569 
       
  1570 static void
       
  1571 handleKeyEvent(jint keyEventId,
       
  1572                XEvent *event,
       
  1573                XtPointer *client_data,
       
  1574                Boolean *cont,
       
  1575                Boolean passEvent)
       
  1576 {
       
  1577     KeySym keysym = NoSymbol;
       
  1578     jint keycode = java_awt_event_KeyEvent_VK_UNDEFINED;
       
  1579     Modifiers mods = 0;
       
  1580     Boolean mapsToUnicodeChar = FALSE;
       
  1581     jint keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;
       
  1582     jint modifiers = 0;
       
  1583 
       
  1584     DTRACE_PRINTLN4("\nEntered handleKeyEvent: type=%d, xkeycode=%x, xstate=%x, keysym=%x",
       
  1585       event->type, event->xkey.keycode, event->xkey.state, keysym);
       
  1586 
       
  1587     if (currentX11InputMethodInstance != NULL
       
  1588         && keyEventId == java_awt_event_KeyEvent_KEY_PRESSED
       
  1589         && event->xkey.window == currentFocusWindow)
       
  1590     {
       
  1591         /* invokes XmbLookupString to get a committed string or keysym if any.  */
       
  1592         if (awt_x11inputmethod_lookupString((XKeyPressedEvent*)event, &keysym)) {
       
  1593             *cont = FALSE;
       
  1594             return;
       
  1595         }
       
  1596     }
       
  1597 
       
  1598     /* Ignore the keysym found immediately above in
       
  1599      * awt_x11inputmethod_lookupString; the methodology in that function
       
  1600      * sometimes returns incorrect results.
       
  1601      *
       
  1602      * Get keysym without taking modifiers into account first.
       
  1603      * This keysym is not necessarily for the character that was typed:
       
  1604      * it is for the primary layer.  So, if $ were typed by pressing
       
  1605      * shift-4, this call should give us 4, not $
       
  1606      *
       
  1607      * We only want this keysym so we can use it to index into the
       
  1608      * keymapTable to get the Java keycode associated with the
       
  1609      * primary layer key that was pressed.
       
  1610      */
       
  1611     keysym = XKeycodeToKeysym(event->xkey.display, event->xkey.keycode, 0);
       
  1612 
       
  1613     /* Linux: Sometimes the keysym returned is uppercase when CapsLock is
       
  1614      * on and LockMask is not set in event->xkey.state.
       
  1615      */
       
  1616     if (keysym >= (KeySym) 'A' && keysym <= (KeySym) 'Z') {
       
  1617         event->xkey.state |= LockMask;
       
  1618         keysym = (KeySym) tolower((int32_t) keysym);
       
  1619     }
       
  1620 
       
  1621     DTRACE_PRINTLN4("In handleKeyEvent: type=%d, xkeycode=%x, xstate=%x, keysym=%x",
       
  1622       event->type, event->xkey.keycode, event->xkey.state, keysym);
       
  1623 
       
  1624     if (keysym == NoSymbol) {
       
  1625         *cont = TRUE;
       
  1626         return;
       
  1627     }
       
  1628 
       
  1629     if (keysym < (KeySym) 256) {
       
  1630         keysymToAWTKeyCode(keysym, &keycode, &mapsToUnicodeChar, &keyLocation);
       
  1631 
       
  1632         /* Now get real keysym which looks at modifiers
       
  1633          * XtGetActionKeySym() returns wrong value with Kana Lock,
       
  1634          * so use XtTranslateKeycode().
       
  1635          */
       
  1636         XtTranslateKeycode(event->xkey.display, (KeyCode) event->xkey.keycode,
       
  1637                            event->xkey.state, &mods, &keysym);
       
  1638         DTRACE_PRINTLN6("%s: type=%d, xkeycode=%x, xstate=%x, keysym=%x, xmods=%d",
       
  1639           "In handleKeyEvent keysym<256 ", event->type, event->xkey.keycode,
       
  1640           event->xkey.state, keysym, mods);
       
  1641 
       
  1642         /* Linux: With caps lock on, chars echo lowercase. */
       
  1643         if ((event->xkey.state & LockMask) &&
       
  1644              (keysym >= (KeySym) 'a' && keysym <= (KeySym) 'z'))
       
  1645         {
       
  1646             keysym = (KeySym) toupper((int32_t) keysym);
       
  1647         }
       
  1648 
       
  1649         if ((event->xkey.state & ControlMask)) {
       
  1650             switch (keysym) {
       
  1651                 case '[':
       
  1652                 case ']':
       
  1653                 case '\\':
       
  1654                 case '_':
       
  1655                     keysym -= 64;
       
  1656                     break;
       
  1657                 default:
       
  1658                     if (isalpha((int32_t) keysym)) {
       
  1659                         keysym = (KeySym) tolower((int32_t) keysym) - 'a' + 1;
       
  1660                     }
       
  1661                     break;
       
  1662             }
       
  1663         }
       
  1664 
       
  1665         if (keysym >= (KeySym) XK_kana_fullstop &&
       
  1666             keysym <= (KeySym) XK_semivoicedsound) {
       
  1667             /*
       
  1668              * 0xff61 is Unicode value of first XK_kana_fullstop.
       
  1669              * We need X Keysym to Unicode map in post1.1 release
       
  1670              * to support more intenational keyboard.
       
  1671              */
       
  1672             keysym = keysym - XK_kana_fullstop + 0xff61;
       
  1673         }
       
  1674 
       
  1675         modifiers = getModifiers(event->xkey.state, 0, keycode);
       
  1676         DTRACE_PRINTLN6("%s: type=%d, xkeycode=%x, xstate=%x, keysym=%x, AWTmodifiers=%d",
       
  1677           "In handleKeyEvent keysym<256 ", event->type, event->xkey.keycode,
       
  1678           event->xkey.state, keysym, modifiers);
       
  1679 
       
  1680         awt_post_java_key_event(client_data,
       
  1681                                 keyEventId,
       
  1682                                 (passEvent == TRUE) ?  event : NULL,
       
  1683                                 event->xkey.time,
       
  1684                                 keycode,
       
  1685                                 (jchar) keysym,
       
  1686                                 modifiers,
       
  1687                                 keyLocation,
       
  1688                                 event);
       
  1689 
       
  1690         if (keyEventId == java_awt_event_KeyEvent_KEY_PRESSED) {
       
  1691             awt_post_java_key_event(client_data,
       
  1692               java_awt_event_KeyEvent_KEY_TYPED,
       
  1693               NULL,
       
  1694               event->xkey.time,
       
  1695               java_awt_event_KeyEvent_VK_UNDEFINED,
       
  1696               (jchar) keysym,
       
  1697               modifiers,
       
  1698               java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN,
       
  1699               event);
       
  1700 
       
  1701         }
       
  1702     } else {
       
  1703         if (event->xkey.state & awt_NumLockMask) {
       
  1704             if( awt_UseType4Patch ) {
       
  1705                 handleKeyEventWithNumLockMask(event, &keysym);
       
  1706             }else{
       
  1707                 handleKeyEventWithNumLockMask_New(event, &keysym);
       
  1708             }
       
  1709         }
       
  1710 
       
  1711         if (keysym == XK_ISO_Left_Tab) {
       
  1712             keysym = XK_Tab;
       
  1713         }
       
  1714 
       
  1715         /* The keysym here does not consider modifiers, so these results
       
  1716          * are relevant to the KEY_PRESSED event only, not the KEY_TYPED
       
  1717          */
       
  1718         keysymToAWTKeyCode(keysym, &keycode, &mapsToUnicodeChar, &keyLocation);
       
  1719         DTRACE_PRINTLN3("In handleKeyEvent: keysym=%x, AWTkeycode=%x, mapsToUnicodeChar=%d",
       
  1720           keysym, keycode, mapsToUnicodeChar);
       
  1721 
       
  1722         if (keycode == java_awt_event_KeyEvent_VK_UNDEFINED) {
       
  1723             *cont = TRUE;
       
  1724             return;
       
  1725         }
       
  1726 
       
  1727         /* Need to take care of keysyms > 0xFFFF here
       
  1728          * Most of these keys don't map to unicode characters, but some do.
       
  1729          *
       
  1730          * For keys that don't map to unicode characters, the keysym
       
  1731          * is irrelevant at this point.  We set the keysym to zero
       
  1732          * to ensure that the switch statement immediately below
       
  1733          * this function call (in adjustKeySym) won't incorrectly act
       
  1734          * on them after the high bits are stripped off.
       
  1735          *
       
  1736          * For keys that do map to unicode characters, we change the keysym
       
  1737          * to the equivalent that is < 0xFFFF
       
  1738          */
       
  1739         handleVendorKeySyms(event, &keysym);
       
  1740 
       
  1741         /* This function is a conglomeration of bug fixes that adjust
       
  1742          * the keysym and XEvent keycode for this key event.
       
  1743          */
       
  1744         adjustKeySym(event, &keysym);
       
  1745 
       
  1746         modifiers = getModifiers(event->xkey.state, 0, keycode);
       
  1747 
       
  1748         DTRACE_PRINTLN6("%s: type=%d, xkeycode=%x, xstate=%x, keysym=%x, xmods=%d",
       
  1749           "In handleKeyEvent keysym>=256 ", event->type, event->xkey.keycode,
       
  1750           event->xkey.state, keysym, mods);
       
  1751         DTRACE_PRINTLN2("                              AWTkeycode=%x, AWTmodifiers=%d",
       
  1752           keycode, modifiers);
       
  1753 
       
  1754         awt_post_java_key_event(client_data,
       
  1755           keyEventId,
       
  1756           (passEvent == TRUE) ? event : NULL,
       
  1757           event->xkey.time,
       
  1758           keycode,
       
  1759           (jchar) (mapsToUnicodeChar ? keysym :
       
  1760             java_awt_event_KeyEvent_CHAR_UNDEFINED),
       
  1761           modifiers,
       
  1762           keyLocation,
       
  1763           event);
       
  1764 
       
  1765         /* If this was a keyPressed event, we may need to post a
       
  1766          * keyTyped event, too.  Otherwise, return.
       
  1767          */
       
  1768         if (keyEventId == java_awt_event_KeyEvent_KEY_RELEASED) {
       
  1769             return;
       
  1770         }
       
  1771         DTRACE_PRINTLN("This is a keyPressed event");
       
  1772 
       
  1773         /* XtTranslateKeycode seems to return slightly bogus values for the
       
  1774          * Escape key (keysym==1004ff69==osfXK_Cancel, xmods=2) on Solaris,
       
  1775          * so we just create the KEY_TYPED as a special case for Escape here.
       
  1776          * (Linux works fine, and this was also okay running under VNC.)
       
  1777          */
       
  1778         if (keycode == java_awt_event_KeyEvent_VK_ESCAPE) {
       
  1779             awt_post_java_key_event(client_data,
       
  1780               java_awt_event_KeyEvent_KEY_TYPED,
       
  1781               NULL,
       
  1782               event->xkey.time,
       
  1783               java_awt_event_KeyEvent_VK_UNDEFINED,
       
  1784               (jchar) keysym,
       
  1785               modifiers,
       
  1786               java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN,
       
  1787               event);
       
  1788 
       
  1789             DTRACE_PRINTLN("Posted a keyTyped event for VK_ESCAPE");
       
  1790             return;
       
  1791         }
       
  1792 
       
  1793         /* Now get real keysym which looks at modifiers for keyTyped event.
       
  1794          * XtGetActionKeySym() returns wrong value with Kana Lock,
       
  1795          * so use XtTranslateKeycode().
       
  1796          */
       
  1797         XtTranslateKeycode(event->xkey.display, (KeyCode) event->xkey.keycode,
       
  1798                            event->xkey.state, &mods, &keysym);
       
  1799         DTRACE_PRINTLN6("%s: type=%d, xkeycode=%x, xstate=%x, keysym=%x, xmods=%d",
       
  1800           "In handleKeyEvent keysym>=256 ", event->type, event->xkey.keycode,
       
  1801           event->xkey.state, keysym, mods);
       
  1802 
       
  1803         if (keysym == NoSymbol) {
       
  1804             return;
       
  1805         }
       
  1806 
       
  1807         if (event->xkey.state & awt_NumLockMask) {
       
  1808             if( awt_UseType4Patch ) {
       
  1809                 handleKeyEventWithNumLockMask(event, &keysym);
       
  1810             }else{
       
  1811                 handleKeyEventWithNumLockMask_New(event, &keysym);
       
  1812             }
       
  1813         }
       
  1814 
       
  1815         if (keysym == XK_ISO_Left_Tab) {
       
  1816             keysym = XK_Tab;
       
  1817         }
       
  1818 
       
  1819         /* Map the real keysym to a Java keycode */
       
  1820         keysymToAWTKeyCode(keysym, &keycode, &mapsToUnicodeChar, &keyLocation);
       
  1821         DTRACE_PRINTLN3("In handleKeyEvent: keysym=%x, AWTkeycode=%x, mapsToUnicodeChar=%d",
       
  1822           keysym, keycode, mapsToUnicodeChar);
       
  1823 
       
  1824         /* If it doesn't map to a Unicode character, don't post a keyTyped event */
       
  1825         if (!mapsToUnicodeChar) {
       
  1826             return;
       
  1827         }
       
  1828 
       
  1829         handleVendorKeySyms(event, &keysym);
       
  1830         adjustKeySym(event, &keysym);
       
  1831         DTRACE_PRINT4("In handleKeyEvent: type=%d, xkeycode=%x, xstate=%x, keysym=%x",
       
  1832           event->type, event->xkey.keycode, event->xkey.state, keysym);
       
  1833         DTRACE_PRINTLN2(", AWTkeycode=%x, AWTmodifiers=%d", keycode, modifiers);
       
  1834 
       
  1835         awt_post_java_key_event(client_data,
       
  1836           java_awt_event_KeyEvent_KEY_TYPED,
       
  1837           NULL,
       
  1838           event->xkey.time,
       
  1839           java_awt_event_KeyEvent_VK_UNDEFINED,
       
  1840           (jchar) keysym,
       
  1841           modifiers,
       
  1842           java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN,
       
  1843           event);
       
  1844     }
       
  1845 }
       
  1846 
       
  1847 
       
  1848 static void
       
  1849 translateXY(Widget w, jint *xp, jint *yp)
       
  1850 {
       
  1851     Position wx, wy;
       
  1852 
       
  1853     XtVaGetValues(w, XmNx, &wx, XmNy, &wy, NULL);
       
  1854     *xp += wx;
       
  1855     *yp += wy;
       
  1856 }
       
  1857 
       
  1858 
       
  1859 /*
       
  1860  * Part fix for bug id 4017222. Return the root widget of the Widget parameter.
       
  1861  */
       
  1862 Widget
       
  1863 getRootWidget(Widget w) {
       
  1864     if(!w) return NULL;
       
  1865 
       
  1866     if(XtParent(w))
       
  1867         return getRootWidget(XtParent(w));
       
  1868     else
       
  1869         return w;
       
  1870 }
       
  1871 
       
  1872 #define ABS(x) ((x) < 0 ? -(x) : (x))
       
  1873 
       
  1874 /* This proc is the major AWT engine for processing X events
       
  1875  * for Java components and is the proc responsible for taking
       
  1876  * X events and posting their corresponding Java event to the
       
  1877  * AWT EventQueue.  It is set up to be called both from an Xt
       
  1878  * event handler and directly from MToolkit.c:shouldDispatchToWidget().
       
  1879  * For the latter case, the "passEvent" parameter will be true,
       
  1880  * which means that the event is being posted on the Java queue
       
  1881  * BEFORE it is being passed to Xt and so a copy of the X event
       
  1882  * must be stored within the Java event structure so it can be
       
  1883  * dispatched to Xt later on.
       
  1884  */
       
  1885 void
       
  1886 awt_canvas_handleEvent(Widget w, XtPointer client_data,
       
  1887                        XEvent * event, struct WidgetInfo *winfo,
       
  1888                        Boolean * cont, Boolean passEvent)
       
  1889 {
       
  1890     static jint clickCount = 1;
       
  1891     static XtPointer lastPeer = NULL;
       
  1892     static Time lastTime = 0;
       
  1893     static jint lastx = 0;
       
  1894     static jint lasty = 0;
       
  1895     static int32_t rbutton = 0;
       
  1896     static int32_t lastButton = 0;
       
  1897     Boolean popupTrigger;
       
  1898     jint x, y;
       
  1899     jint modifiers = 0;
       
  1900     jint button = java_awt_event_MouseEvent_NOBUTTON;
       
  1901     uint32_t fullRelease = 0;
       
  1902     WidgetClass wclass = NULL;
       
  1903 
       
  1904     /* Any event handlers which take peer instance pointers as
       
  1905      * client_data should check to ensure the widget has not been
       
  1906      * marked as destroyed as a result of a dispose() call on the peer
       
  1907      * (which can result in the peer instance pointer already haven
       
  1908      * been gc'd by the time this event is processed)
       
  1909      */
       
  1910     if (w->core.being_destroyed) {
       
  1911         return;
       
  1912     }
       
  1913     *cont = FALSE;
       
  1914 
       
  1915     switch (event->type) {
       
  1916         case SelectionClear:
       
  1917         case SelectionNotify:
       
  1918         case SelectionRequest:
       
  1919             *cont = TRUE;
       
  1920             break;
       
  1921         case GraphicsExpose:
       
  1922         case Expose:
       
  1923             HandleExposeEvent(w, (jobject) client_data, event);
       
  1924             break;
       
  1925         case FocusIn:
       
  1926         case FocusOut:
       
  1927             *cont = TRUE;
       
  1928             updateCursor(client_data, CACHE_UPDATE); // 4840883
       
  1929             // We no longer listen to the Motif focus notifications.
       
  1930             // Instead we call focus callbacks in the times we think
       
  1931             // appropriate trying to simulate correct Motif widget system
       
  1932             // behavior.
       
  1933             break;
       
  1934         case ButtonPress:
       
  1935             x = (jint) event->xbutton.x;
       
  1936             y = (jint) event->xbutton.y;
       
  1937 
       
  1938             if (lastPeer == client_data &&
       
  1939                 lastButton == event->xbutton.button &&
       
  1940                 (event->xbutton.time - lastTime) <= (Time) awt_multiclick_time) {
       
  1941                     clickCount++;
       
  1942             } else {
       
  1943                 clickCount = 1;
       
  1944                 lastPeer = client_data;
       
  1945                 lastButton = event->xbutton.button;
       
  1946                 lastx = x;
       
  1947                 lasty = y;
       
  1948             }
       
  1949             lastTime = event->xbutton.time;
       
  1950 
       
  1951             /* On MouseEvent.MOUSE_PRESSED, RELEASED and CLICKED  only new modifiers and
       
  1952              * modifier for changed mouse button are set.
       
  1953              */
       
  1954             button = getButton(event->xbutton.button);
       
  1955             modifiers = getModifiers(event->xbutton.state, button, 0);
       
  1956 
       
  1957 
       
  1958             /* If the widget is a subwidget on a component we need to
       
  1959              * translate the x,y into the coordinate space of the component.
       
  1960              */
       
  1961             if (winfo != NULL && winfo->widget != winfo->origin) {
       
  1962                 translateXY(winfo->widget, &x, &y);
       
  1963             }
       
  1964 
       
  1965             if (XtIsSubclass(w, xmScrollBarWidgetClass) && findWidgetInfo(w) != NULL) {
       
  1966                 passEvent = FALSE;
       
  1967                 *cont = TRUE;
       
  1968             }
       
  1969 
       
  1970             /* Mouse wheel events come in as button 4 (wheel up) and
       
  1971              * button 5 (wheel down).
       
  1972              */
       
  1973             if (lastButton == 4 || lastButton == 5) {
       
  1974                 *cont = FALSE;
       
  1975                 awt_post_java_mouse_event(client_data,
       
  1976                                           java_awt_event_MouseEvent_MOUSE_WHEEL,
       
  1977                                           (passEvent == TRUE) ? event : NULL,
       
  1978                                           event->xbutton.time,
       
  1979                                           modifiers,
       
  1980                                           x, y,
       
  1981                                           (jint) (event->xbutton.x_root),
       
  1982                                           (jint) (event->xbutton.y_root),
       
  1983                                           clickCount,
       
  1984                                           False,
       
  1985                                           lastButton == 4 ? -1 : 1,
       
  1986                                           java_awt_event_MouseEvent_NOBUTTON);
       
  1987                 /* we're done with this event */
       
  1988                 break;
       
  1989             }
       
  1990 
       
  1991             /* (4168006) Find out out how many buttons we have
       
  1992              * If this is a two button system Right == 2
       
  1993              * If this is a three button system Right == 3
       
  1994              */
       
  1995             if ( rbutton == 0 ) {
       
  1996                 unsigned char map[5];
       
  1997                 rbutton = XGetPointerMapping ( awt_display, map, 3 );
       
  1998             }
       
  1999 
       
  2000             if (event->xbutton.button == rbutton || event->xbutton.button > 2) {
       
  2001                 popupTrigger = True;
       
  2002             } else {
       
  2003                 popupTrigger = False;
       
  2004             }
       
  2005 
       
  2006             awt_post_java_mouse_event(client_data,
       
  2007                                       java_awt_event_MouseEvent_MOUSE_PRESSED,
       
  2008                                       (passEvent == TRUE) ? event : NULL,
       
  2009                                       event->xbutton.time,
       
  2010                                       modifiers,
       
  2011                                       x, y,
       
  2012                                       (jint) (event->xbutton.x_root),
       
  2013                                       (jint) (event->xbutton.y_root),
       
  2014                                       clickCount,
       
  2015                                       popupTrigger, 0,
       
  2016                                       button);
       
  2017 
       
  2018             drag_source = w;
       
  2019 
       
  2020             break;
       
  2021         case ButtonRelease:
       
  2022             if (XtIsSubclass(w, xmScrollBarWidgetClass) && findWidgetInfo(w) != NULL) {
       
  2023                 passEvent = FALSE;
       
  2024                 *cont = TRUE;
       
  2025             }
       
  2026 
       
  2027             /*
       
  2028              * For button 4 & 5 (mouse wheel) we can simply ignore this event.
       
  2029              * We dispatch the wheel on the ButtonPress.
       
  2030              */
       
  2031             if (event->xbutton.button == 4 ||
       
  2032                 event->xbutton.button == 5) {
       
  2033                 break;
       
  2034             }
       
  2035 
       
  2036             prevWidget = NULL;
       
  2037             x = (jint) event->xbutton.x;
       
  2038             y = (jint) event->xbutton.y;
       
  2039             /* On MouseEvent.MOUSE_PRESSED, RELEASED and CLICKED  only new modifiers and
       
  2040              * modifier for changed mouse button are set.
       
  2041              */
       
  2042             button = getButton(event->xbutton.button);
       
  2043             modifiers = getModifiers(event->xbutton.state, button, 0);
       
  2044 
       
  2045             fullRelease =
       
  2046               ((event->xbutton.state & Button1Mask) &&
       
  2047                !(event->xbutton.state & Button2Mask) &&
       
  2048                !(event->xbutton.state & Button3Mask) &&
       
  2049                (event->xbutton.button == Button1)) ||
       
  2050               (!(event->xbutton.state & Button1Mask) &&
       
  2051                (event->xbutton.state & Button2Mask) &&
       
  2052                !(event->xbutton.state & Button3Mask) &&
       
  2053                (event->xbutton.button == Button2)) ||
       
  2054               (!(event->xbutton.state & Button1Mask) &&
       
  2055                !(event->xbutton.state & Button2Mask) &&
       
  2056                (event->xbutton.state & Button3Mask) &&
       
  2057                (event->xbutton.button == Button3));
       
  2058 
       
  2059             /* If the widget is a subwidget on a component we need to
       
  2060              * translate the x,y into the coordinate space of the component.
       
  2061              */
       
  2062             if (winfo != NULL && winfo->widget != winfo->origin) {
       
  2063                 translateXY(winfo->widget, &x, &y);
       
  2064             }
       
  2065             drag_source = NULL;
       
  2066             awt_post_java_mouse_event(client_data,
       
  2067                                       java_awt_event_MouseEvent_MOUSE_RELEASED,
       
  2068                                       (passEvent == TRUE) ? event : NULL,
       
  2069                                       event->xbutton.time,
       
  2070                                       modifiers,
       
  2071                                       x, y,
       
  2072                                       (jint) (event->xbutton.x_root),
       
  2073                                       (jint) (event->xbutton.y_root),
       
  2074                                       clickCount,
       
  2075                                       FALSE, 0,
       
  2076                                       button);
       
  2077 
       
  2078             if (lastPeer == client_data) {
       
  2079                 awt_post_java_mouse_event(client_data,
       
  2080                                           java_awt_event_MouseEvent_MOUSE_CLICKED,
       
  2081                                           NULL,
       
  2082                                           event->xbutton.time,
       
  2083                                           modifiers,
       
  2084                                           x, y,
       
  2085                                           (jint) (event->xbutton.x_root),
       
  2086                                           (jint) (event->xbutton.y_root),
       
  2087                                           clickCount,
       
  2088                                           FALSE, 0,
       
  2089                                           button);
       
  2090             }
       
  2091 
       
  2092             if (fullRelease) {
       
  2093                 updateCursor(client_data, UPDATE_ONLY);
       
  2094             }
       
  2095 
       
  2096         break;
       
  2097         case MotionNotify:
       
  2098             if (XtIsSubclass(w, xmScrollBarWidgetClass) && findWidgetInfo(w) != NULL) {
       
  2099                 passEvent = FALSE;
       
  2100                 *cont = TRUE;
       
  2101             }
       
  2102 
       
  2103             x = (jint) event->xmotion.x;
       
  2104             y = (jint) event->xmotion.y;
       
  2105 
       
  2106             /* If a motion comes in while a multi-click is pending,
       
  2107              * allow a smudge factor so that moving the mouse by a small
       
  2108              * amount does not wipe out the multi-click state variables.
       
  2109              */
       
  2110             if (!(lastPeer == client_data &&
       
  2111                   ((event->xmotion.time - lastTime) <= (Time) awt_multiclick_time) &&
       
  2112                   (ABS(lastx - x) < awt_multiclick_smudge &&
       
  2113                    ABS(lasty - y) < awt_multiclick_smudge))) {
       
  2114                 clickCount = (jint) 0;
       
  2115                 lastTime = (Time) 0;
       
  2116                 lastPeer = NULL;
       
  2117                 lastx = (jint) 0;
       
  2118                 lasty = (jint) 0;
       
  2119             }
       
  2120             /* On other MouseEvent only new modifiers and
       
  2121              * old mouse modifiers are set.
       
  2122              */
       
  2123             modifiers = getModifiers(event->xmotion.state, 0, 0);
       
  2124 
       
  2125             /* If the widget is a subwidget on a component we need to
       
  2126              * translate the x,y into the coordinate space of the component.
       
  2127              */
       
  2128             if (winfo != NULL && winfo->widget != winfo->origin) {
       
  2129                 translateXY(winfo->widget, &x, &y);
       
  2130             }
       
  2131             if (event->xmotion.state & (Button1Mask | Button2Mask | Button3Mask)) {
       
  2132                 if (!clickCount) {
       
  2133 
       
  2134             /*
       
  2135                 Fix for bug id 4017222. A button is down, so EnterNotify and
       
  2136                 LeaveNotify events are only being sent to this widget. If
       
  2137                 the pointer has moved over a new widget, manually generate
       
  2138                 MouseEnter and MouseExit and send them to the right widgets.
       
  2139             */
       
  2140 
       
  2141                 extern Widget awt_WidgetAtXY(Widget root, Position x, Position y);
       
  2142                 extern Widget awt_GetWidgetAtPointer();
       
  2143                 Widget currentWidget=NULL, topLevelW;
       
  2144                 Position wx=0, wy=0;
       
  2145 
       
  2146                 XtTranslateCoords(w, (int32_t) x, (int32_t) y, &wx, &wy);
       
  2147                 /* Get the top level widget underneath the mouse pointer */
       
  2148                 currentWidget = awt_GetWidgetAtPointer();
       
  2149                 /* Get the exact widget at the current XY from the top level */
       
  2150                 currentWidget = awt_WidgetAtXY(currentWidget, wx, wy);
       
  2151                 if ((prevWidget != NULL) && (prevWidget != w) &&
       
  2152                     (currentWidget != prevWidget) && awt_isAwtWidget(prevWidget) &&
       
  2153                     !prevWidget->core.being_destroyed) {
       
  2154                     XtPointer userData=NULL;
       
  2155                     XtVaGetValues(prevWidget, XmNuserData, &userData, NULL);
       
  2156                     if (userData) {
       
  2157                         awt_post_java_mouse_event(userData,
       
  2158                             java_awt_event_MouseEvent_MOUSE_EXITED,
       
  2159                             (passEvent==TRUE) ? event : NULL,
       
  2160                             event->xmotion.time,
       
  2161                             modifiers,
       
  2162                             x, y,
       
  2163                             (jint) (event->xmotion.x_root),
       
  2164                             (jint) (event->xmotion.y_root),
       
  2165                             clickCount,
       
  2166                             FALSE, 0,
       
  2167                             java_awt_event_MouseEvent_NOBUTTON);
       
  2168                     }
       
  2169                 }
       
  2170 
       
  2171                 if ((currentWidget != NULL) && (currentWidget != w) &&
       
  2172                     (currentWidget != prevWidget) && awt_isAwtWidget(currentWidget)) {
       
  2173                     XtPointer userData=NULL;
       
  2174                     XtVaGetValues(currentWidget, XmNuserData, &userData, NULL);
       
  2175                     if (userData) {
       
  2176                         awt_post_java_mouse_event(userData,
       
  2177                             java_awt_event_MouseEvent_MOUSE_ENTERED,
       
  2178                             (passEvent==TRUE) ? event : NULL,
       
  2179                             event->xmotion.time,
       
  2180                             modifiers,
       
  2181                             x, y,
       
  2182                             (jint) (event->xmotion.x_root),
       
  2183                             (jint) (event->xmotion.y_root),
       
  2184                             clickCount,
       
  2185                             FALSE, 0,
       
  2186                             java_awt_event_MouseEvent_NOBUTTON);
       
  2187                     }
       
  2188 
       
  2189                     updateCursor(userData, CACHE_ONLY);
       
  2190                     awt_util_setCursor(currentWidget, None);
       
  2191                 }
       
  2192 
       
  2193                 prevWidget = currentWidget;
       
  2194                 /* end 4017222 */
       
  2195 
       
  2196 
       
  2197                 awt_post_java_mouse_event(client_data,
       
  2198                                           java_awt_event_MouseEvent_MOUSE_DRAGGED,
       
  2199                                           (passEvent == TRUE) ? event : NULL,
       
  2200                                           event->xmotion.time,
       
  2201                                           modifiers,
       
  2202                                           x, y,
       
  2203                                           (jint) (event->xmotion.x_root),
       
  2204                                           (jint) (event->xmotion.y_root),
       
  2205                                           clickCount,
       
  2206                                           FALSE, 0,
       
  2207                                           java_awt_event_MouseEvent_NOBUTTON);
       
  2208 
       
  2209             }
       
  2210             } else {
       
  2211 
       
  2212                 awt_post_java_mouse_event(client_data,
       
  2213                                           java_awt_event_MouseEvent_MOUSE_MOVED,
       
  2214                                           (passEvent == TRUE) ? event : NULL,
       
  2215                                           event->xmotion.time,
       
  2216                                           modifiers,
       
  2217                                           x, y,
       
  2218                                           (jint) (event->xmotion.x_root),
       
  2219                                           (jint) (event->xmotion.y_root),
       
  2220                                           clickCount,
       
  2221                                           FALSE, 0,
       
  2222                                           java_awt_event_MouseEvent_NOBUTTON);
       
  2223             }
       
  2224             break;
       
  2225         case KeyPress:
       
  2226             handleKeyEvent(java_awt_event_KeyEvent_KEY_PRESSED,
       
  2227                            event, client_data, cont, TRUE);
       
  2228             break;
       
  2229         case KeyRelease:
       
  2230             handleKeyEvent(java_awt_event_KeyEvent_KEY_RELEASED,
       
  2231                            event, client_data, cont, TRUE);
       
  2232             break;
       
  2233         case EnterNotify:
       
  2234         case LeaveNotify:
       
  2235 /*
       
  2236   printf("----->%s on %s(%x):mode=%d detail = %d\n",
       
  2237   event->type == EnterNotify?"EnterNotify":"LeaveNotify",
       
  2238   XtName(w), w,
       
  2239   ((XCrossingEvent*)event)->mode, ((XCrossingEvent*)event)->detail);
       
  2240 */
       
  2241         if (event->xcrossing.mode != NotifyNormal ||
       
  2242                 ((event->xcrossing.detail == NotifyVirtual ||
       
  2243                   event->xcrossing.detail == NotifyNonlinearVirtual) &&
       
  2244                  !XtIsSubclass(w, xmScrolledWindowWidgetClass))) {
       
  2245                 *cont = TRUE;
       
  2246                 return;
       
  2247             }
       
  2248 
       
  2249             /* fix for 4454304.
       
  2250              * We should not post MOUSE_ENTERED and MOUSE_EXITED events
       
  2251              * if the mouse pointer is in the place between component
       
  2252              * and its scrollbars.
       
  2253              * kdm@sparc.spb.su
       
  2254              */
       
  2255             if (winfo != NULL && winfo->widget != NULL) {
       
  2256                 wclass = XtClass(winfo->widget);
       
  2257                 if (event->xcrossing.subwindow == NULL
       
  2258                     && event->xcrossing.detail == NotifyInferior
       
  2259                     && (wclass == xmTextWidgetClass
       
  2260                         || wclass == xmListWidgetClass)) {
       
  2261                     *cont = TRUE;
       
  2262                     return;
       
  2263                 }
       
  2264             }
       
  2265 
       
  2266             clickCount = (jint) 0;
       
  2267             lastTime = (Time) 0;
       
  2268             lastPeer = NULL;
       
  2269 
       
  2270             /* On other MouseEvent only new modifiers and
       
  2271              * old mouse modifiers are set.
       
  2272              */
       
  2273             modifiers = getModifiers(event->xcrossing.state, 0, 0);
       
  2274 
       
  2275             switch (event->type) {
       
  2276                 case EnterNotify:
       
  2277                     awt_post_java_mouse_event(client_data,
       
  2278                                               java_awt_event_MouseEvent_MOUSE_ENTERED,
       
  2279                                               (passEvent == TRUE) ? event : NULL,
       
  2280                                               event->xcrossing.time,
       
  2281                                               modifiers,
       
  2282                                               (jint) (event->xcrossing.x),
       
  2283                                               (jint) (event->xcrossing.y),
       
  2284                                               (jint) (event->xcrossing.x_root),
       
  2285                                               (jint) (event->xcrossing.y_root),
       
  2286                                               clickCount,
       
  2287                                               FALSE, 0,
       
  2288                                               java_awt_event_MouseEvent_NOBUTTON);
       
  2289                     if (!(event->xcrossing.state
       
  2290                         & (Button1Mask | Button2Mask | Button3Mask))) {
       
  2291                         updateCursor(client_data, CACHE_UPDATE);
       
  2292                     }
       
  2293 
       
  2294                     break;
       
  2295                 case LeaveNotify:
       
  2296                     awt_post_java_mouse_event(client_data,
       
  2297                                               java_awt_event_MouseEvent_MOUSE_EXITED,
       
  2298                                               (passEvent == TRUE) ? event : NULL,
       
  2299                                               event->xcrossing.time,
       
  2300                                               modifiers,
       
  2301                                               (jint) (event->xcrossing.x),
       
  2302                                               (jint) (event->xcrossing.y),
       
  2303                                               (jint) (event->xcrossing.x_root),
       
  2304                                               (jint) (event->xcrossing.y_root),
       
  2305                                               clickCount,
       
  2306                                               FALSE, 0,
       
  2307                                               java_awt_event_MouseEvent_NOBUTTON);
       
  2308                     break;
       
  2309             }
       
  2310             break;
       
  2311 
       
  2312         default:
       
  2313             break;
       
  2314     }
       
  2315 }
       
  2316 
       
  2317 /*
       
  2318  * client_data is MComponentPeer subclass
       
  2319  */
       
  2320 void
       
  2321 awt_canvas_event_handler(Widget w, XtPointer client_data,
       
  2322                          XEvent * event, Boolean * cont)
       
  2323 {
       
  2324     awt_canvas_handleEvent(w, client_data, event, NULL, cont, FALSE);
       
  2325 }
       
  2326 
       
  2327 void
       
  2328 awt_canvas_reconfigure(struct FrameData *wdata)
       
  2329 {
       
  2330     Dimension w, h;
       
  2331 
       
  2332     if (wdata->winData.comp.widget == NULL ||
       
  2333         XtParent(wdata->winData.comp.widget) == NULL) {
       
  2334         return;
       
  2335     }
       
  2336     XtVaGetValues(XtParent(wdata->winData.comp.widget), XmNwidth, &w, XmNheight, &h, NULL);
       
  2337     XtConfigureWidget(wdata->winData.comp.widget,
       
  2338                       -(wdata->left),
       
  2339                       -(wdata->top),
       
  2340                       w + (wdata->left + wdata->right),
       
  2341                       h + (wdata->top + wdata->bottom),
       
  2342                       0);
       
  2343 }
       
  2344 
       
  2345 static void
       
  2346 Wrap_event_handler(Widget widget,
       
  2347                    XtPointer client_data,
       
  2348                    XmDrawingAreaCallbackStruct * call_data)
       
  2349 {
       
  2350     awt_canvas_reconfigure((struct FrameData *) client_data);
       
  2351 }
       
  2352 
       
  2353 
       
  2354 Widget
       
  2355 awt_canvas_create(XtPointer this,
       
  2356                   Widget parent,
       
  2357                   char *base,
       
  2358                   int32_t width,
       
  2359                   int32_t height,
       
  2360                   Boolean parentIsFrame,
       
  2361                   struct FrameData *wdata,
       
  2362                   AwtGraphicsConfigDataPtr awtData)
       
  2363 {
       
  2364     Widget newCanvas;
       
  2365     Widget wrap;
       
  2366 #define MAX_ARGC 20
       
  2367     Arg args[MAX_ARGC];
       
  2368     int32_t argc;
       
  2369     char name[128];
       
  2370     static XtTranslations translationKeyDown = NULL;
       
  2371 
       
  2372     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  2373 
       
  2374 
       
  2375     if (parent == NULL) {
       
  2376         JNU_ThrowNullPointerException(env, "NullPointerException");
       
  2377         return NULL;
       
  2378     }
       
  2379     if (width == 0) {
       
  2380         width = 1;
       
  2381     }
       
  2382     if (height == 0) {
       
  2383         height = 1;
       
  2384     }
       
  2385 
       
  2386     if (wdata != NULL) {
       
  2387         argc = 0;
       
  2388         if  (!parentIsFrame)
       
  2389         {
       
  2390             XtSetArg(args[argc], XmNwidth, width);
       
  2391             argc++;
       
  2392             XtSetArg(args[argc], XmNheight, height);
       
  2393             argc++;
       
  2394         }
       
  2395         XtSetArg(args[argc], XmNmarginWidth, 0);
       
  2396         argc++;
       
  2397         XtSetArg(args[argc], XmNmarginHeight, 0);
       
  2398         argc++;
       
  2399         XtSetArg(args[argc], XmNspacing, 0);
       
  2400         argc++;
       
  2401         XtSetArg(args[argc], XmNresizePolicy, XmRESIZE_NONE);
       
  2402         argc++;
       
  2403         /* check for overflowing name? */
       
  2404         strcpy(name, base);
       
  2405         strcat(name, "wrap");
       
  2406 
       
  2407         DASSERT(!(argc > MAX_ARGC));
       
  2408         wrap = XmCreateDrawingArea(parent, name, args, argc);
       
  2409         if  (!parentIsFrame)
       
  2410         {
       
  2411             /* Fixing bugs in frame module (awt_Frame.c).  It will now
       
  2412                provide the resize handling for this inner/parent canvas.*/
       
  2413             XtAddCallback(wrap, XmNresizeCallback,
       
  2414                           (XtCallbackProc) Wrap_event_handler, wdata);
       
  2415         }
       
  2416         XtManageChild(wrap);
       
  2417     } else {
       
  2418         wrap = parent;
       
  2419     }
       
  2420 
       
  2421     /* check for overflowing name? */
       
  2422     strcpy(name, base);
       
  2423     strcat(name, "canvas");
       
  2424 
       
  2425     argc = 0;
       
  2426     XtSetArg(args[argc], XmNspacing, 0);
       
  2427     argc++;
       
  2428     if  (!parentIsFrame)
       
  2429     {
       
  2430         XtSetArg(args[argc], XmNwidth, width);
       
  2431         argc++;
       
  2432         XtSetArg(args[argc], XmNheight, height);
       
  2433         argc++;
       
  2434     }
       
  2435     XtSetArg(args[argc], XmNmarginHeight, 0);
       
  2436     argc++;
       
  2437     XtSetArg(args[argc], XmNmarginWidth, 0);
       
  2438     argc++;
       
  2439     XtSetArg(args[argc], XmNresizePolicy, XmRESIZE_NONE);
       
  2440     argc++;
       
  2441     XtSetArg(args[argc], XmNuserData, this);
       
  2442     argc++;
       
  2443     /* Fixed 4059430, 3/11/98, robi.khan@eng
       
  2444      * install insert proc callback so components are ordered correctly
       
  2445      * when added directly to frame/dialogs/windows
       
  2446      */
       
  2447     XtSetArg(args[argc], XmNinsertPosition, (XtPointer) awt_util_insertCallback);
       
  2448     argc++;
       
  2449 
       
  2450     if (awtData != getDefaultConfig(awtData->awt_visInfo.screen)) {
       
  2451         XtSetArg (args[argc], XtNvisual, awtData->awt_visInfo.visual); argc++;
       
  2452         XtSetArg (args[argc], XmNdepth, awtData->awt_depth); argc++;
       
  2453         XtSetArg (args[argc], XmNscreen,
       
  2454                   ScreenOfDisplay(awt_display,
       
  2455                                   awtData->awt_visInfo.screen)); argc++;
       
  2456 
       
  2457         if (awtData->awt_cmap == None) {
       
  2458             awtJNI_CreateColorData (env, awtData, 1);
       
  2459         }
       
  2460 
       
  2461         XtSetArg (args[argc], XmNcolormap, awtData->awt_cmap); argc++;
       
  2462 
       
  2463         DASSERT(!(argc > MAX_ARGC));
       
  2464         newCanvas = XtCreateWidget(name, vDrawingAreaClass, wrap,
       
  2465                                    args, argc);
       
  2466 
       
  2467     } else {
       
  2468         newCanvas = XtCreateWidget(name, xDrawingAreaClass,
       
  2469             wrap, args, argc);
       
  2470     }
       
  2471 
       
  2472     XtSetMappedWhenManaged(newCanvas, False);
       
  2473     XtManageChild(newCanvas);
       
  2474 /*
       
  2475   XXX: causes problems on 2.5
       
  2476   if (!scrollBugWorkAround) {
       
  2477   awt_setWidgetGravity(newCanvas, StaticGravity);
       
  2478   }
       
  2479 */
       
  2480     /* Fixed 4250354 7/28/99 ssi@sparc.spb.su
       
  2481      * XtParseTranslationTable leaks in old ver of Xtoolkit
       
  2482      * and result should be deletetd in any case
       
  2483      *
       
  2484      * XtOverrideTranslations(newCanvas,
       
  2485      *                      XtParseTranslationTable("<KeyDown>:DrawingAreaInput()"));
       
  2486      */
       
  2487     if (NULL==translationKeyDown)
       
  2488         translationKeyDown=XtParseTranslationTable("<KeyDown>:DrawingAreaInput()");
       
  2489     XtOverrideTranslations(newCanvas,translationKeyDown);
       
  2490 
       
  2491     XtSetSensitive(newCanvas, True);
       
  2492 
       
  2493     return newCanvas;
       
  2494 }
       
  2495 
       
  2496 static void
       
  2497 messWithGravity(Widget w, int32_t gravity)
       
  2498 {
       
  2499     extern void awt_changeAttributes(Display * dpy, Widget w,
       
  2500                                      unsigned long mask,
       
  2501                                      XSetWindowAttributes * xattr);
       
  2502     XSetWindowAttributes xattr;
       
  2503 
       
  2504     xattr.bit_gravity = gravity;
       
  2505     xattr.win_gravity = gravity;
       
  2506 
       
  2507     awt_changeAttributes(XtDisplay(w), w, (CWBitGravity | CWWinGravity), &xattr);
       
  2508 
       
  2509 }
       
  2510 
       
  2511 struct MoveRecord {
       
  2512     long dx;
       
  2513     long dy;
       
  2514 };
       
  2515 
       
  2516 void
       
  2517 moveWidget(Widget w, void *data)
       
  2518 {
       
  2519     struct MoveRecord *rec = (struct MoveRecord *) data;
       
  2520 
       
  2521     if (XtIsRealized(w) && XmIsRowColumn(w)) {
       
  2522         w->core.x -= rec->dx;
       
  2523         w->core.y -= rec->dy;
       
  2524     }
       
  2525 }
       
  2526 
       
  2527 #if 0
       
  2528 /* Scroll entire contents of window by dx and dy.  Currently only
       
  2529    dy is supported.  A negative dy means scroll backwards, i.e.,
       
  2530    contents in window move down. */
       
  2531 void
       
  2532 awt_canvas_scroll(XtPointer this,
       
  2533                   struct CanvasData *wdata,
       
  2534                   long dx,
       
  2535                   long dy)
       
  2536 {
       
  2537 
       
  2538     Window win;
       
  2539     XWindowChanges xchgs;
       
  2540     Window root;
       
  2541     int x, y;
       
  2542     unsigned int width, height, junk;
       
  2543     Display *dpy;
       
  2544     struct MoveRecord mrec;
       
  2545 
       
  2546     mrec.dx = dx;
       
  2547     mrec.dy = dy;
       
  2548 
       
  2549     dpy = XtDisplay(wdata->comp.widget);
       
  2550     win = XtWindow(wdata->comp.widget);
       
  2551 
       
  2552     /* REMIND: consider getting rid of this! */
       
  2553     XGetGeometry(awt_display,
       
  2554                  win,
       
  2555                  &root,
       
  2556                  &x,
       
  2557                  &y,
       
  2558                  &width,
       
  2559                  &height,
       
  2560                  &junk,
       
  2561                  &junk);
       
  2562 
       
  2563     /* we need to actually update the coordinates for manager widgets, */
       
  2564     /* otherwise the parent won't pass down events to them properly */
       
  2565     /* after scrolling... */
       
  2566     awt_util_mapChildren(wdata->comp.widget, moveWidget, 0, &mrec);
       
  2567 
       
  2568     if (dx < 0) {
       
  2569         /* scrolling backward */
       
  2570 
       
  2571         if (scrollBugWorkAround) {
       
  2572             messWithGravity(wdata->comp.widget, NorthWestGravity);
       
  2573         }
       
  2574         xchgs.x = x + dx;
       
  2575         xchgs.y = y;
       
  2576         xchgs.width = width - dx;
       
  2577         xchgs.height = height;
       
  2578         XConfigureWindow(awt_display,
       
  2579                          win,
       
  2580                          CWX | CWY | CWWidth | CWHeight,
       
  2581                          &xchgs);
       
  2582 
       
  2583         if (scrollBugWorkAround) {
       
  2584             messWithGravity(wdata->comp.widget, NorthWestGravity);
       
  2585         }
       
  2586         xchgs.x = x;
       
  2587         xchgs.y = y;
       
  2588         XConfigureWindow(awt_display,
       
  2589                          win,
       
  2590                          CWX | CWY,
       
  2591                          &xchgs);
       
  2592 
       
  2593         xchgs.width = width;
       
  2594         xchgs.height = height;
       
  2595         XConfigureWindow(awt_display,
       
  2596                          win,
       
  2597                          CWWidth | CWHeight,
       
  2598                          &xchgs);
       
  2599     } else {
       
  2600         /* forward scrolling */
       
  2601 
       
  2602         /* make window a little taller */
       
  2603         xchgs.width = width + dx;
       
  2604         xchgs.height = height;
       
  2605         XConfigureWindow(awt_display,
       
  2606                          win,
       
  2607                          CWWidth | CWHeight,
       
  2608                          &xchgs);
       
  2609 
       
  2610         if (scrollBugWorkAround) {
       
  2611             messWithGravity(wdata->comp.widget, NorthEastGravity);
       
  2612         }
       
  2613         /* move window by amount we're scrolling */
       
  2614         xchgs.x = x - dx;
       
  2615         xchgs.y = y;
       
  2616         XConfigureWindow(awt_display,
       
  2617                          win,
       
  2618                          CWX | CWY,
       
  2619                          &xchgs);
       
  2620 
       
  2621         if (scrollBugWorkAround) {
       
  2622             messWithGravity(wdata->comp.widget, NorthWestGravity);
       
  2623         }
       
  2624         /* resize to original size */
       
  2625         xchgs.x = x;
       
  2626         xchgs.y = y;
       
  2627         xchgs.width = width;
       
  2628         xchgs.height = height;
       
  2629         XConfigureWindow(awt_display,
       
  2630                          win,
       
  2631                          CWX | CWY | CWWidth | CWHeight,
       
  2632                          &xchgs);
       
  2633     }
       
  2634     /* Because of the weird way we're scrolling this window,
       
  2635        we have to eat all the exposure events that result from
       
  2636        scrolling forward, and translate them up by the amount we're
       
  2637        scrolling by.
       
  2638 
       
  2639        Rather than just eating all the exposures and having the
       
  2640        java code fill in what it knows is exposed, we do it this
       
  2641        way.  The reason is that there might be some other exposure
       
  2642        events caused by overlapping windows on top of us that we
       
  2643        also need to deal with. */
       
  2644     {
       
  2645         XRectangle rect;
       
  2646 
       
  2647         rect.x = -1;
       
  2648         eatAllExposures(dpy, win, &rect);
       
  2649         if (rect.x != -1) {         /* we got at least one expose event */
       
  2650             if (dx > 0) {
       
  2651                 rect.x -= dx;
       
  2652                 rect.width += dx;
       
  2653             }
       
  2654 /*
       
  2655   printf("EXPOSE (%d): %d, %d, %d, %d\n",
       
  2656   dy, rect.x, rect.y, rect.width, rect.height);
       
  2657 */
       
  2658             callJavaExpose(this, &rect);
       
  2659             XSync(awt_display, False);
       
  2660         }
       
  2661     }
       
  2662     if (dy < 0) {
       
  2663         /* scrolling backward */
       
  2664 
       
  2665         if (scrollBugWorkAround) {
       
  2666             messWithGravity(wdata->comp.widget, SouthGravity);
       
  2667         }
       
  2668         xchgs.x = x;
       
  2669         xchgs.y = y + dy;
       
  2670         xchgs.width = width;
       
  2671         xchgs.height = height - dy;
       
  2672         XConfigureWindow(awt_display,
       
  2673                          win,
       
  2674                          CWX | CWY | CWWidth | CWHeight,
       
  2675                          &xchgs);
       
  2676 
       
  2677         if (scrollBugWorkAround) {
       
  2678             messWithGravity(wdata->comp.widget, NorthWestGravity);
       
  2679         }
       
  2680         xchgs.x = x;
       
  2681         xchgs.y = y;
       
  2682         XConfigureWindow(awt_display,
       
  2683                          win,
       
  2684                          CWX | CWY,
       
  2685                          &xchgs);
       
  2686 
       
  2687         xchgs.width = width;
       
  2688         xchgs.height = height;
       
  2689         XConfigureWindow(awt_display,
       
  2690                          win,
       
  2691                          CWWidth | CWHeight,
       
  2692                          &xchgs);
       
  2693     } else {
       
  2694         /* forward scrolling */
       
  2695 
       
  2696         /* make window a little taller */
       
  2697         xchgs.width = width;
       
  2698         xchgs.height = height + dy;
       
  2699         XConfigureWindow(awt_display,
       
  2700                          win,
       
  2701                          CWWidth | CWHeight,
       
  2702                          &xchgs);
       
  2703 
       
  2704         /* move window by amount we're scrolling */
       
  2705         xchgs.x = x;
       
  2706         xchgs.y = y - dy;
       
  2707         XConfigureWindow(awt_display,
       
  2708                          win,
       
  2709                          CWX | CWY,
       
  2710                          &xchgs);
       
  2711 
       
  2712         if (scrollBugWorkAround) {
       
  2713             messWithGravity(wdata->comp.widget, SouthGravity);
       
  2714         }
       
  2715         /* resize to original size */
       
  2716         xchgs.x = x;
       
  2717         xchgs.y = y;
       
  2718         xchgs.width = width;
       
  2719         xchgs.height = height;
       
  2720         XConfigureWindow(awt_display,
       
  2721                          win,
       
  2722                          CWX | CWY | CWWidth | CWHeight,
       
  2723                          &xchgs);
       
  2724         if (scrollBugWorkAround) {
       
  2725             messWithGravity(wdata->comp.widget, NorthWestGravity);
       
  2726         }
       
  2727     }
       
  2728     /* Because of the weird way we're scrolling this window,
       
  2729        we have to eat all the exposure events that result from
       
  2730        scrolling forward, and translate them up by the amount we're
       
  2731        scrolling by.
       
  2732 
       
  2733        Rather than just eating all the exposures and having the
       
  2734        java code fill in what it knows is exposed, we do it this
       
  2735        way.  The reason is that there might be some other exposure
       
  2736        events caused by overlapping windows on top of us that we
       
  2737        also need to deal with. */
       
  2738     {
       
  2739         XRectangle rect;
       
  2740 
       
  2741         rect.x = -1;
       
  2742         eatAllExposures(dpy, win, &rect);
       
  2743         if (rect.x != -1) {         /* we got at least one expose event */
       
  2744             if (dy > 0) {
       
  2745                 rect.y -= dy;
       
  2746                 rect.height += dy;
       
  2747             }
       
  2748             if (dx > 0) {
       
  2749                 rect.x -= dx;
       
  2750                 rect.width += dx;
       
  2751             }
       
  2752 /*
       
  2753   printf("EXPOSE (%d): %d, %d, %d, %d\n",
       
  2754   dy, rect.x, rect.y, rect.width, rect.height);
       
  2755 */
       
  2756             callJavaExpose(this, &rect);
       
  2757             XSync(awt_display, False);
       
  2758         }
       
  2759     }
       
  2760 }
       
  2761 #endif
       
  2762 
       
  2763 extern Window focusProxyWindow;
       
  2764 /*
       
  2765  * client_data is MComponentPeer instance
       
  2766  */
       
  2767 void
       
  2768 awt_post_java_key_event(XtPointer client_data, jint id, XEvent *event,
       
  2769   Time when, jint keycode, jchar keychar, jint modifiers, jint keyLocation, XEvent *anEvent)
       
  2770 {
       
  2771     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  2772     jobject peer = (jobject) client_data;
       
  2773     jobject target;
       
  2774     static jclass classKeyEvent = NULL;
       
  2775     static jmethodID mid = NULL;
       
  2776     char *clsName = "java/awt/event/KeyEvent";
       
  2777     jobject hEvent;
       
  2778     jlong jWhen;
       
  2779     Boolean isProxyActive = (focusProxyWindow != None);
       
  2780 
       
  2781     if (anEvent != NULL && anEvent->xany.send_event == 2){
       
  2782         isProxyActive = False;
       
  2783         if (event != NULL) {
       
  2784             event->xany.send_event = 0;
       
  2785         }
       
  2786     }
       
  2787     if ((*env)->PushLocalFrame(env, 16) < 0)
       
  2788         return;
       
  2789 
       
  2790     target = (*env)->GetObjectField(env, peer, mComponentPeerIDs.target);
       
  2791 
       
  2792     if (classKeyEvent == NULL) {
       
  2793         jobject sysClass;
       
  2794 
       
  2795         sysClass = (*env)->FindClass(env, clsName);
       
  2796         if (sysClass != NULL) {
       
  2797             /* Make this class 'sticky', we don't want it GC'd */
       
  2798             classKeyEvent = (*env)->NewGlobalRef(env, sysClass);
       
  2799             mid = (*env)->GetMethodID(env, classKeyEvent, "<init>",
       
  2800               "(Ljava/awt/Component;IJIICIZ)V");
       
  2801         }
       
  2802         if (JNU_IsNull(env, classKeyEvent) || mid == NULL) {
       
  2803             JNU_ThrowClassNotFoundException(env, clsName);
       
  2804             (*env)->PopLocalFrame(env, 0);
       
  2805             return;
       
  2806         }
       
  2807     }
       
  2808 
       
  2809     jWhen = awt_util_nowMillisUTC_offset(when); /* convert Time to UTC */
       
  2810 
       
  2811     hEvent = (*env)->NewObject(env, classKeyEvent, mid,
       
  2812                                target, id, jWhen, modifiers,
       
  2813                                keycode, keychar, keyLocation,
       
  2814                                isProxyActive?JNI_TRUE:JNI_FALSE);
       
  2815 
       
  2816     if ((*env)->ExceptionOccurred(env)) {
       
  2817         (*env)->ExceptionDescribe(env);
       
  2818         (*env)->ExceptionClear(env);
       
  2819     }
       
  2820     if (JNU_IsNull(env, hEvent)) {
       
  2821         JNU_ThrowNullPointerException(env, "NullPointerException: constructor failed.");
       
  2822         (*env)->PopLocalFrame(env, 0);
       
  2823         return;
       
  2824     }
       
  2825     awt_copyXEventToAWTEvent(env, event, hEvent);
       
  2826     #ifdef DEBUG
       
  2827     if (debugKeys) {
       
  2828         jio_fprintf(stderr, "native posting event id:%d  keychar:%c\n", (int)id, (char)keychar);
       
  2829     }
       
  2830     #endif
       
  2831     JNU_CallMethodByName(env, NULL, peer,
       
  2832                          "postEvent", "(Ljava/awt/AWTEvent;)V", hEvent);
       
  2833     if ((*env)->ExceptionOccurred(env)) {
       
  2834         (*env)->ExceptionDescribe(env);
       
  2835         (*env)->ExceptionClear(env);
       
  2836     }
       
  2837     (*env)->PopLocalFrame(env, 0);
       
  2838 } /* awt_post_java_key_event() */
       
  2839 
       
  2840 /*
       
  2841  * Note: this routine returns a global reference which should be deleted
       
  2842  * after use.
       
  2843  */
       
  2844 jobject
       
  2845 awt_canvas_wrapInSequenced(jobject awtevent) {
       
  2846     static jclass classSequencedEvent = NULL;
       
  2847     static jmethodID mid = NULL;
       
  2848     jobject wrapperEventLocal = NULL;
       
  2849     jobject wrapperEvent = NULL;
       
  2850 
       
  2851     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  2852 
       
  2853     if ((*env)->PushLocalFrame(env, 5) < 0)
       
  2854         return NULL;
       
  2855 
       
  2856     if (classSequencedEvent == NULL) {
       
  2857         jobject sysClass = (*env)->FindClass(env, "java/awt/SequencedEvent");
       
  2858         if (sysClass != NULL) {
       
  2859             /* Make this class 'sticky', we don't want it GC'd */
       
  2860             classSequencedEvent = (*env)->NewGlobalRef(env, sysClass);
       
  2861             if (mid == NULL) {
       
  2862               mid = (*env)->GetMethodID(env, classSequencedEvent
       
  2863                                         ,"<init>"
       
  2864                                         ,"(Ljava/awt/AWTEvent;)V");
       
  2865             }
       
  2866         }
       
  2867         if (JNU_IsNull(env, classSequencedEvent) || mid == NULL) {
       
  2868             JNU_ThrowClassNotFoundException(env, "java/awt/SequencedEvent");
       
  2869             (*env)->PopLocalFrame(env, 0);
       
  2870             return NULL;
       
  2871         }
       
  2872     }
       
  2873     wrapperEventLocal = (*env)->NewObject(env, classSequencedEvent, mid, awtevent);
       
  2874 
       
  2875     if ((*env)->ExceptionOccurred(env)) {
       
  2876         (*env)->ExceptionDescribe(env);
       
  2877         (*env)->ExceptionClear(env);
       
  2878     }
       
  2879     if (JNU_IsNull(env, wrapperEventLocal)) {
       
  2880         JNU_ThrowNullPointerException(env, "constructor failed.");
       
  2881         (*env)->PopLocalFrame(env, 0);
       
  2882         return NULL;
       
  2883     }
       
  2884     wrapperEvent = (*env)->NewGlobalRef(env, wrapperEventLocal);
       
  2885     if (!JNU_IsNull(env, ((*env)->ExceptionOccurred(env)))) {
       
  2886         (*env)->ExceptionDescribe(env);
       
  2887         (*env)->ExceptionClear(env);
       
  2888         (*env)->PopLocalFrame(env, 0);
       
  2889         return NULL;
       
  2890     }
       
  2891     if (JNU_IsNull(env, wrapperEvent)) {
       
  2892         JNU_ThrowNullPointerException(env, "NewGlobalRef failed.");
       
  2893         (*env)->PopLocalFrame(env, 0);
       
  2894         return NULL;
       
  2895     }
       
  2896 
       
  2897     (*env)->PopLocalFrame(env, 0);
       
  2898     return wrapperEvent;
       
  2899 }
       
  2900 
       
  2901 jobject
       
  2902 findTopLevelOpposite(JNIEnv *env, jint eventType)
       
  2903 {
       
  2904     jobject target, peer, opposite;
       
  2905 
       
  2906     if ((*env)->EnsureLocalCapacity(env, 2) < 0) {
       
  2907         return NULL;
       
  2908     }
       
  2909 
       
  2910     /* 4462056: Get a usable handle for a weakly referenced object */
       
  2911     target = (*env)->NewLocalRef(env,
       
  2912                  (eventType == java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS)
       
  2913                                  ? forGained
       
  2914                                  : focusList->requestor);
       
  2915     if (target == NULL) {
       
  2916         return NULL;
       
  2917     }
       
  2918 
       
  2919     peer = (*env)->GetObjectField(env, target, componentIDs.peer);
       
  2920     (*env)->DeleteLocalRef(env, target);
       
  2921     if (peer == NULL) {
       
  2922         return NULL;
       
  2923     }
       
  2924 
       
  2925     opposite = findTopLevel(peer, env);
       
  2926     (*env)->DeleteLocalRef(env, peer);
       
  2927 
       
  2928     return opposite;
       
  2929 }
       
  2930 
       
  2931 void
       
  2932 cleanFocusList(JNIEnv *env){
       
  2933 
       
  2934   while(focusList) {
       
  2935     FocusListElt *tmp = focusList->next;
       
  2936     (*env)->DeleteWeakGlobalRef(env, focusList->requestor);
       
  2937     free(focusList);
       
  2938     focusList = tmp;
       
  2939   }
       
  2940   focusListEnd = NULL;
       
  2941 }
       
  2942 
       
  2943 static jweak
       
  2944 computeOpposite(jint id, jobject target)
       
  2945 {
       
  2946     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  2947     jobject top;
       
  2948     jboolean isSameObject;
       
  2949 
       
  2950     if (focusList == NULL) {
       
  2951         return NULL;
       
  2952     }
       
  2953 
       
  2954     /* 4462056: Get a usable handle for a weakly referenced object */
       
  2955     top = (*env)->NewLocalRef(env, focusList->requestor);
       
  2956     if (top == NULL) {
       
  2957         /* weakly referenced component was deleted -- clean up focus list */
       
  2958         cleanFocusList(env);
       
  2959         return NULL;
       
  2960     }
       
  2961 
       
  2962     isSameObject = (*env)->IsSameObject(env, target, top);
       
  2963     (*env)->DeleteLocalRef(env, top);
       
  2964 
       
  2965     if (isSameObject) {
       
  2966         if (id == java_awt_event_FocusEvent_FOCUS_GAINED) {
       
  2967             return forGained;
       
  2968         } else { /* focus lost */
       
  2969             FocusListElt *tmp = focusList->next;
       
  2970             (*env)->DeleteWeakGlobalRef(env, forGained);
       
  2971             forGained = focusList->requestor;
       
  2972             free(focusList);
       
  2973             focusList = tmp;
       
  2974 
       
  2975             if (focusList == NULL) {
       
  2976                 focusListEnd = NULL;
       
  2977                 return NULL;
       
  2978             }
       
  2979             return focusList->requestor;
       
  2980         }
       
  2981     } else { /* target does not match top of list */
       
  2982         /* be gentle with focus lost for now... */
       
  2983         if (id == java_awt_event_FocusEvent_FOCUS_LOST) {
       
  2984             (*env)->DeleteWeakGlobalRef(env, forGained);
       
  2985             forGained = (*env)->NewWeakGlobalRef(env, target);
       
  2986             return NULL;
       
  2987         }
       
  2988 
       
  2989         cleanFocusList(env);
       
  2990         return NULL;
       
  2991     }
       
  2992 }
       
  2993 
       
  2994 
       
  2995 /*
       
  2996  * client_data is MComponentPeer instance
       
  2997  */
       
  2998 void
       
  2999 awt_post_java_focus_event(XtPointer client_data,
       
  3000                           jint id, jobject cause,
       
  3001                           XEvent* event)
       
  3002 {
       
  3003     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  3004     jobject peer = (jobject) client_data;
       
  3005     jobject target;
       
  3006     jobject opposite;
       
  3007     static jclass classFocusEvent = NULL;
       
  3008     static jmethodID mid = NULL;
       
  3009     char *clsName = "sun/awt/CausedFocusEvent";
       
  3010     jobject hEvent;
       
  3011 
       
  3012     if ((*env)->PushLocalFrame(env, 16) < 0)
       
  3013         return;
       
  3014 
       
  3015     target = (*env)->GetObjectField(env, peer, mComponentPeerIDs.target);
       
  3016 
       
  3017     opposite = (*env)->NewLocalRef(env, computeOpposite(id, target));
       
  3018 
       
  3019    if (classFocusEvent == NULL) {
       
  3020         jobject sysClass;
       
  3021 
       
  3022         sysClass = (*env)->FindClass(env, clsName);
       
  3023         if (sysClass != NULL) {
       
  3024             /* Make this class 'sticky', we don't want it GC'd */
       
  3025             classFocusEvent = (*env)->NewGlobalRef(env, sysClass);
       
  3026             mid = (*env)->GetMethodID(env, classFocusEvent
       
  3027                                       ,"<init>"
       
  3028                                       ,"(Ljava/awt/Component;IZLjava/awt/Component;Lsun/awt/CausedFocusEvent$Cause;)V");
       
  3029         }
       
  3030         if (JNU_IsNull(env, classFocusEvent) || mid == 0) {
       
  3031             JNU_ThrowClassNotFoundException(env, clsName);
       
  3032             (*env)->PopLocalFrame(env, 0);
       
  3033             return;
       
  3034         }
       
  3035     }
       
  3036     hEvent = (*env)->NewObject(env, classFocusEvent, mid,
       
  3037                                target, id, JNI_FALSE, opposite, cause);
       
  3038     (*env)->DeleteLocalRef(env, opposite);
       
  3039 
       
  3040     if ((*env)->ExceptionOccurred(env)) {
       
  3041         (*env)->ExceptionDescribe(env);
       
  3042         (*env)->ExceptionClear(env);
       
  3043     }
       
  3044     if (JNU_IsNull(env, hEvent)) {
       
  3045         JNU_ThrowNullPointerException(env, "NullPointerException: constructor failed.");
       
  3046         (*env)->PopLocalFrame(env, 0);
       
  3047         return;
       
  3048     }
       
  3049     awt_copyXEventToAWTEvent(env, event, hEvent);
       
  3050     {
       
  3051         jobject awtEvent = awt_canvas_wrapInSequenced(hEvent);
       
  3052         JNU_CallMethodByName(env, NULL, peer,
       
  3053                              "postEvent", "(Ljava/awt/AWTEvent;)V",
       
  3054                              awtEvent);
       
  3055         (*env)->DeleteGlobalRef(env, awtEvent);
       
  3056     }
       
  3057     if ((*env)->ExceptionOccurred(env)) {
       
  3058         (*env)->ExceptionDescribe(env);
       
  3059         (*env)->ExceptionClear(env);
       
  3060     }
       
  3061     (*env)->PopLocalFrame(env, 0);
       
  3062 }
       
  3063 
       
  3064 
       
  3065 void
       
  3066 awt_canvas_addToFocusListDefault(jobject target) {
       
  3067     awt_canvas_addToFocusListWithDuplicates(target, JNI_FALSE);
       
  3068 }
       
  3069 
       
  3070 void
       
  3071 awt_canvas_addToFocusListWithDuplicates(jobject target, jboolean acceptDuplicates)
       
  3072 {
       
  3073     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  3074     jboolean isSameObject;
       
  3075 
       
  3076     if (focusListEnd) {
       
  3077         jobject localRef = (*env)->NewLocalRef(env, focusListEnd->requestor);
       
  3078 
       
  3079         if (localRef == NULL) {
       
  3080             isSameObject = JNI_FALSE;
       
  3081         } else {
       
  3082             isSameObject = (*env)->IsSameObject(env, target, localRef);
       
  3083             (*env)->DeleteLocalRef(env, localRef);
       
  3084         }
       
  3085 
       
  3086         if (isSameObject && !acceptDuplicates) {
       
  3087             return;
       
  3088         }
       
  3089 
       
  3090         focusListEnd->next = malloc(sizeof(FocusListElt));
       
  3091         focusListEnd = focusListEnd->next;
       
  3092     } else {
       
  3093         jobject l_focusOwnerPeer = awt_canvas_getFocusOwnerPeer();
       
  3094         if (l_focusOwnerPeer == NULL) {
       
  3095             isSameObject = JNI_FALSE;
       
  3096         } else {
       
  3097             jobject l_focusOwner =
       
  3098                 (*env)->GetObjectField(env, l_focusOwnerPeer,
       
  3099                                        mComponentPeerIDs.target);
       
  3100             isSameObject =
       
  3101                 (*env)->IsSameObject(env, target, l_focusOwner);
       
  3102             (*env)->DeleteLocalRef(env, l_focusOwner);
       
  3103             (*env)->DeleteLocalRef(env, l_focusOwnerPeer);
       
  3104         }
       
  3105 
       
  3106         if (isSameObject && !acceptDuplicates) {
       
  3107             return;
       
  3108         }
       
  3109 
       
  3110         focusList = focusListEnd = malloc(sizeof(FocusListElt));
       
  3111     }
       
  3112 
       
  3113     focusListEnd->requestor = (*env)->NewWeakGlobalRef(env, target);
       
  3114     focusListEnd->next = NULL;
       
  3115 }
       
  3116 
       
  3117 /*
       
  3118  * client_data is MComponentPeer instance
       
  3119  */
       
  3120 void
       
  3121 awt_post_java_mouse_event(XtPointer client_data, jint id, XEvent* event,
       
  3122                           Time when, jint modifiers, jint x, jint y,
       
  3123                           jint xAbs, jint yAbs,
       
  3124                           jint clickcount,
       
  3125                           Boolean popuptrigger,
       
  3126                           jint wheelAmt, jint button)
       
  3127 {
       
  3128     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  3129     jobject peer = (jobject) client_data;
       
  3130     jobject target;
       
  3131 
       
  3132     static jclass classMouseEvent = NULL;
       
  3133     static jclass classMouseWheelEvent = NULL;
       
  3134 
       
  3135     static jmethodID mid = NULL;
       
  3136     static jmethodID wheelmid = NULL;
       
  3137 
       
  3138     char *clsName = "java/awt/event/MouseEvent";
       
  3139     char *wheelClsName = "java/awt/event/MouseWheelEvent";
       
  3140 
       
  3141     jobject hEvent;
       
  3142     jobject sysClass;
       
  3143     jlong jWhen;
       
  3144 
       
  3145     if ((*env)->PushLocalFrame(env, 16) < 0)
       
  3146         return;
       
  3147 
       
  3148     target = (*env)->GetObjectField(env, peer, mComponentPeerIDs.target);
       
  3149 
       
  3150     if (classMouseEvent == NULL) {
       
  3151         sysClass = (*env)->FindClass(env, clsName);
       
  3152         if (sysClass != NULL) {
       
  3153             /* Make this class 'sticky', we don't want it GC'd */
       
  3154             classMouseEvent = (*env)->NewGlobalRef(env, sysClass);
       
  3155             mid = (*env)->GetMethodID(env, classMouseEvent
       
  3156                                       ,"<init>"
       
  3157                                       ,"(Ljava/awt/Component;IJIIIIIIZI)V");
       
  3158         }
       
  3159         if (JNU_IsNull(env, classMouseEvent) || mid == 0) {
       
  3160             JNU_ThrowClassNotFoundException(env, clsName);
       
  3161             (*env)->PopLocalFrame(env, 0);
       
  3162             return;
       
  3163         }
       
  3164     }
       
  3165 
       
  3166     if (id == java_awt_event_MouseEvent_MOUSE_WHEEL &&
       
  3167         classMouseWheelEvent == NULL) {
       
  3168         sysClass = (*env)->FindClass(env, wheelClsName);
       
  3169         if (sysClass != NULL) {
       
  3170             /* Make this class 'sticky', we don't want it GC'd */
       
  3171             classMouseWheelEvent = (*env)->NewGlobalRef(env, sysClass);
       
  3172             wheelmid = (*env)->GetMethodID(env, classMouseWheelEvent,
       
  3173                                        "<init>",
       
  3174                                        "(Ljava/awt/Component;IJIIIIIIZIII)V");
       
  3175         }
       
  3176         if (JNU_IsNull(env, classMouseWheelEvent) || wheelmid == 0) {
       
  3177             JNU_ThrowClassNotFoundException(env, wheelClsName);
       
  3178             (*env)->PopLocalFrame(env, 0);
       
  3179             return;
       
  3180         }
       
  3181     }
       
  3182 
       
  3183     jWhen = awt_util_nowMillisUTC_offset(when); /* convert Time to UTC */
       
  3184 
       
  3185     if (id == java_awt_event_MouseEvent_MOUSE_WHEEL) {
       
  3186         hEvent = (*env)->NewObject(env, classMouseWheelEvent, wheelmid,
       
  3187                               target, id, jWhen, modifiers,
       
  3188                               x, y,
       
  3189                               xAbs, yAbs,
       
  3190                               clickcount, popuptrigger,
       
  3191                               /* Linux has no API for setting how a Component
       
  3192                                * should scroll in response to the mouse wheel,
       
  3193                                * so we have to make up our own.
       
  3194                                * The default behavior on Windows is 3 lines of
       
  3195                                * text, so we use that to match.
       
  3196                                */
       
  3197                               java_awt_event_MouseWheelEvent_WHEEL_UNIT_SCROLL,
       
  3198                               3,
       
  3199                               wheelAmt);
       
  3200     }
       
  3201     else {
       
  3202         hEvent = (*env)->NewObject(env, classMouseEvent, mid,
       
  3203                                    target, id, jWhen, modifiers,
       
  3204                                    x, y,
       
  3205                                    xAbs, yAbs,
       
  3206                                    clickcount, popuptrigger, button);
       
  3207     }
       
  3208 
       
  3209 
       
  3210     if ((*env)->ExceptionOccurred(env)) {
       
  3211         (*env)->ExceptionDescribe(env);
       
  3212         (*env)->ExceptionClear(env);
       
  3213     }
       
  3214     if (JNU_IsNull(env, hEvent)) {
       
  3215         JNU_ThrowNullPointerException(env, "NullPointerException: constructor failed.");
       
  3216         (*env)->PopLocalFrame(env, 0);
       
  3217         return;
       
  3218     }
       
  3219     awt_copyXEventToAWTEvent(env, event, hEvent);
       
  3220     JNU_CallMethodByName(env, NULL, peer,
       
  3221                          "postEvent", "(Ljava/awt/AWTEvent;)V", hEvent);
       
  3222     if ((*env)->ExceptionOccurred(env)) {
       
  3223         (*env)->ExceptionDescribe(env);
       
  3224         (*env)->ExceptionClear(env);
       
  3225     }
       
  3226     (*env)->PopLocalFrame(env, 0);
       
  3227 }