This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gui][PATCH] keyboard focus management updates


Hi,

This patch contains some updates to the focus management
implementation.  Java KeyEvents are now converted back to GDK key events
after they have passed through Java's focus managment system.  The patch
also contains other miscellaneous fixes.

Committed to java-gui-branch.

Tom

2004-05-06  Thomas Fitzsimmons  <fitzsim@redhat.com>

	* gnu/java/awt/peer/gtk/GtkComponentPeer.java
	(gtkWidgetRequestFocus): Mark protected.
	(GtkComponentPeer): Only set the peer's bounds if its component
	is valid.
	* java/awt/Component.java (static): Set the default keyboard
	focus manager.
	(requestFocus(), requestFocus(boolean), requestFocusInWindow(),
	requestFocusInWindow(temporary)): Don't request focus if the
	component is not showing.  Get tree lock before traversing
	component hierarchy.
	* java/awt/DefaultKeyboardFocusManager.java (dispatchEvent):
	Only set the global focus owner if it is not a Window.
	(processKeyEvent): Consume keystrokes associated with the focus
	traversal keystroke.
	(focusPreviousComponent, focusNextComponent, upFocusCycle,
	downFocusCycle): Call requestFocusInWindow instead of
	requestFocus.
	* java/awt/EventDispatchThread.java (run): Move setting of
	default keyboard focus manager to Component.java.
	* jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c
	(awt_keycode_to_keysym): New function.
	(gtkWidgetDispatchKeyEvent): Finish implementation.
	* jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c
	(pre_event_handler): Add FIXME comment.

Index: gnu/java/awt/peer/gtk/GtkComponentPeer.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/awt/peer/gtk/GtkComponentPeer.java,v
retrieving revision 1.16.2.5
diff -u -r1.16.2.5 GtkComponentPeer.java
--- gnu/java/awt/peer/gtk/GtkComponentPeer.java	22 Apr 2004 20:26:31 -0000	1.16.2.5
+++ gnu/java/awt/peer/gtk/GtkComponentPeer.java	7 May 2004 00:10:28 -0000
@@ -93,7 +93,7 @@
   native void gtkWidgetSetCursor (int type);
   native void gtkWidgetSetBackground (int red, int green, int blue);
   native void gtkWidgetSetForeground (int red, int green, int blue);
-  native void gtkWidgetRequestFocus ();
+  native protected void gtkWidgetRequestFocus ();
   native void gtkWidgetDispatchKeyEvent (int id, long when, int mods,
                                          int keyCode, char keyChar, int keyLocation);
   native void gtkSetFont (String name, int style, int size);
@@ -143,10 +143,14 @@
                                                      awtComponent.getX(), 
                                                      awtComponent.getY(),
                                                      dims[0], dims[1]);
-      }      
-      Rectangle bounds = awtComponent.getBounds ();
-      setBounds (bounds.x, bounds.y, bounds.width, bounds.height);
+      }
+
+      if (awtComponent.isValid ())
+        {
+          Rectangle bounds = awtComponent.getBounds ();
 
+          setBounds (bounds.x, bounds.y, bounds.width, bounds.height);
+        }
     } catch (RuntimeException ex) { ; }
   }
 
@@ -476,7 +480,7 @@
 			       int keyCode, char keyChar, int keyLocation)
   {
     q.postEvent (new KeyEvent (awtComponent, id, when, mods,
-    			       keyCode, keyChar, keyLocation));
+                               keyCode, keyChar, keyLocation));
   }
 
   protected void postFocusEvent (int id, boolean temporary)
Index: java/awt/Component.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/awt/Component.java,v
retrieving revision 1.37.2.8
diff -u -r1.37.2.8 Component.java
--- java/awt/Component.java	22 Apr 2004 17:47:36 -0000	1.37.2.8
+++ java/awt/Component.java	7 May 2004 00:10:29 -0000
@@ -571,6 +571,8 @@
   {
     incrementalDraw = Boolean.getBoolean ("awt.image.incrementalDraw");
     redrawRate = Long.getLong ("awt.image.redrawrate");
+    // Set the default KeyboardFocusManager.
+    KeyboardFocusManager.setCurrentKeyboardFocusManager (null);
   }
 
   // Public and protected API.
@@ -3635,7 +3637,7 @@
    * that its top-level ancestor become the focused Window.
    *
    * For the request to be granted, the Component must be focusable,
-   * displayable and visible and the top-level Window to which it
+   * displayable and showing and the top-level Window to which it
    * belongs must be focusable.  If the request is initially denied on
    * the basis that the top-level Window is not focusable, the request
    * will be remembered and granted when the Window does become
@@ -3657,36 +3659,38 @@
   public void requestFocus ()
   {
     if (isDisplayable ()
-	&& isVisible ()
+	&& isShowing ()
 	&& isFocusable ())
       {
-	// FIXME: need to get the tree lock here.
-	// Find this Component's top-level ancestor.
-        Container parent = getParent ();
+        synchronized (getTreeLock ())
+          {
+            // Find this Component's top-level ancestor.
+            Container parent = getParent ();
 
-        while (parent != null
-	       && !(parent instanceof Window))
-	  parent = parent.getParent ();
+            while (parent != null
+                   && !(parent instanceof Window))
+              parent = parent.getParent ();
 
-	Window toplevel = (Window) parent;
-	if (toplevel.isFocusableWindow ())
-	  {
-	    if (peer != null)
-	      // This call will cause a FOCUS_GAINED event to be
-	      // posted to the system event queue if the native
-	      // windowing system grants the focus request.
-	      peer.requestFocus ();
-	    else
-	      {
-		// Either our peer hasn't been created yet or we're a
-		// lightweight component.  In either case we want to
-		// post a FOCUS_GAINED event.
-		EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
-		eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED));
-	      }
-	  }
-	else
-	  pendingFocusRequest = new FocusEvent(this, FocusEvent.FOCUS_GAINED);
+            Window toplevel = (Window) parent;
+            if (toplevel.isFocusableWindow ())
+              {
+                if (peer != null)
+                  // This call will cause a FOCUS_GAINED event to be
+                  // posted to the system event queue if the native
+                  // windowing system grants the focus request.
+                  peer.requestFocus ();
+                else
+                  {
+                    // Either our peer hasn't been created yet or we're a
+                    // lightweight component.  In either case we want to
+                    // post a FOCUS_GAINED event.
+                    EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
+                    eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED));
+                  }
+              }
+            else
+              pendingFocusRequest = new FocusEvent(this, FocusEvent.FOCUS_GAINED);
+          }
       }
   }
 
@@ -3695,7 +3699,7 @@
    * that its top-level ancestor become the focused Window.
    *
    * For the request to be granted, the Component must be focusable,
-   * displayable and visible and the top-level Window to which it
+   * displayable and showing and the top-level Window to which it
    * belongs must be focusable.  If the request is initially denied on
    * the basis that the top-level Window is not focusable, the request
    * will be remembered and granted when the Window does become
@@ -3728,39 +3732,41 @@
   protected boolean requestFocus (boolean temporary)
   {
     if (isDisplayable ()
-	&& isVisible ()
+	&& isShowing ()
 	&& isFocusable ())
       {
-	// FIXME: need to get the tree lock here.
-	// Find this Component's top-level ancestor.
-        Container parent = getParent ();
+        synchronized (getTreeLock ())
+          {
+            // Find this Component's top-level ancestor.
+            Container parent = getParent ();
 
-        while (parent != null
-	       && !(parent instanceof Window))
-	  parent = parent.getParent ();
+            while (parent != null
+                   && !(parent instanceof Window))
+              parent = parent.getParent ();
 
-	Window toplevel = (Window) parent;
-	if (toplevel.isFocusableWindow ())
-	  {
-	    if (peer != null)
-	      // This call will cause a FOCUS_GAINED event to be
-	      // posted to the system event queue if the native
-	      // windowing system grants the focus request.
-	      peer.requestFocus ();
-	    else
-	      {
-		// Either our peer hasn't been created yet or we're a
-		// lightweight component.  In either case we want to
-		// post a FOCUS_GAINED event.
-		EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
-		eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, temporary));
-	      }
-	  }
-	else
-	  // FIXME: need to add a focus listener to our top-level
-	  // ancestor, so that we can post this event when it becomes
-	  // the focused window.
-	  pendingFocusRequest = new FocusEvent(this, FocusEvent.FOCUS_GAINED, temporary);
+            Window toplevel = (Window) parent;
+            if (toplevel.isFocusableWindow ())
+              {
+                if (peer != null)
+                  // This call will cause a FOCUS_GAINED event to be
+                  // posted to the system event queue if the native
+                  // windowing system grants the focus request.
+                  peer.requestFocus ();
+                else
+                  {
+                    // Either our peer hasn't been created yet or we're a
+                    // lightweight component.  In either case we want to
+                    // post a FOCUS_GAINED event.
+                    EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
+                    eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, temporary));
+                  }
+              }
+            else
+              // FIXME: need to add a focus listener to our top-level
+              // ancestor, so that we can post this event when it becomes
+              // the focused window.
+              pendingFocusRequest = new FocusEvent(this, FocusEvent.FOCUS_GAINED, temporary);
+          }
       }
     // Always return true.
     return true;
@@ -3771,7 +3777,7 @@
    * its top-level ancestor is the currently focused Window.  A
    * <code>FOCUS_GAINED</code> event will be fired if and only if this
    * request is successful. To be successful, the component must be
-   * displayable, visible, and focusable, and its ancestor top-level
+   * displayable, showing, and focusable, and its ancestor top-level
    * Window must be focused.
    *
    * If the return value is false, the request is guaranteed to fail.
@@ -3799,7 +3805,7 @@
    * its top-level ancestor is the currently focused Window.  A
    * <code>FOCUS_GAINED</code> event will be fired if and only if this
    * request is successful. To be successful, the component must be
-   * displayable, visible, and focusable, and its ancestor top-level
+   * displayable, showing, and focusable, and its ancestor top-level
    * Window must be focused.
    *
    * If the return value is false, the request is guaranteed to fail.
@@ -3826,39 +3832,47 @@
 
     Window focusedWindow = manager.getFocusedWindow ();
 
-    if (focusedWindow != null)
+    if (isDisplayable ()
+	&& isShowing ()
+	&& isFocusable ())
       {
-	// FIXME: get tree lock here.
-	Container parent = getParent ();
-
-	while (parent != null
-	       && !(parent instanceof Window))
-	  parent = parent.getParent ();
+        if (focusedWindow != null)
+          {
+            synchronized (getTreeLock ())
+              {
+                Container parent = getParent ();
 
-	Window toplevel = (Window) parent;
+                while (parent != null
+                       && !(parent instanceof Window))
+                  parent = parent.getParent ();
+
+                Window toplevel = (Window) parent;
+
+                // Check if top-level ancestor is currently focused window.
+                if (focusedWindow == toplevel)
+                  {
+                    if (peer != null)
+                      // This call will cause a FOCUS_GAINED event to be
+                      // posted to the system event queue if the native
+                      // windowing system grants the focus request.
+                      peer.requestFocus ();
+                    else
+                      {
+                        // Either our peer hasn't been created yet or we're a
+                        // lightweight component.  In either case we want to
+                        // post a FOCUS_GAINED event.
+                        EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
+                        eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, temporary));
+                      }
+                  }
+                else
+                  return false;
+              }
+          }
 
-	// Check if top-level ancestor is currently focused window.
-	if (focusedWindow == toplevel)
-	  {
-	    if (peer != null)
-	      // This call will cause a FOCUS_GAINED event to be
-	      // posted to the system event queue if the native
-	      // windowing system grants the focus request.
-	      peer.requestFocus ();
-	    else
-	      {
-		// Either our peer hasn't been created yet or we're a
-		// lightweight component.  In either case we want to
-		// post a FOCUS_GAINED event.
-		EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
-		eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, temporary));
-	      }
-	  }
-	else
-	  return false;
+        return true;
       }
-
-    return true;
+    return false;
   }
 
   /**
Index: java/awt/DefaultKeyboardFocusManager.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/awt/DefaultKeyboardFocusManager.java,v
retrieving revision 1.1.54.2
diff -u -r1.1.54.2 DefaultKeyboardFocusManager.java
--- java/awt/DefaultKeyboardFocusManager.java	22 Apr 2004 20:26:32 -0000	1.1.54.2
+++ java/awt/DefaultKeyboardFocusManager.java	7 May 2004 00:10:29 -0000
@@ -162,7 +162,8 @@
       {
         Component target = (Component) e.getSource ();
 
-        if (e.id == FocusEvent.FOCUS_GAINED)
+        if (e.id == FocusEvent.FOCUS_GAINED
+            && !(target instanceof Window))
           {
             if (((FocusEvent) e).isTemporary ())
               setGlobalFocusOwner (target);
@@ -170,7 +171,9 @@
               setGlobalPermanentFocusOwner (target);
           }
 
-        target.dispatchEvent (e);
+        if (!(target instanceof Window))
+          target.dispatchEvent (e);
+
         return true;
       }
     else if (e instanceof KeyEvent)
@@ -245,8 +248,6 @@
     if (postProcessKeyEvent (e))
       return true;
 
-    // FIXME: how do we "pass the event to the peers for processing"?
-
     // Always return true.
     return true;
   }
@@ -312,7 +313,14 @@
 
   public void processKeyEvent (Component comp, KeyEvent e)
   {
-    AWTKeyStroke keystroke = AWTKeyStroke.getAWTKeyStrokeForEvent (e);
+    AWTKeyStroke eventKeystroke = AWTKeyStroke.getAWTKeyStrokeForEvent (e);
+    // For every focus traversal keystroke, we need to also consume
+    // the other two key event types for the same key (e.g. if
+    // KEY_PRESSED TAB is a focus traversal keystroke, we also need to
+    // consume KEY_RELEASED and KEY_TYPED TAB key events).
+    AWTKeyStroke oppositeKeystroke = AWTKeyStroke.getAWTKeyStroke (e.getKeyCode (),
+                                                                   e.getModifiers (),
+                                                                   !(e.id == KeyEvent.KEY_RELEASED));
 
     Set forwardKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
     Set backwardKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
@@ -321,27 +329,33 @@
     if (comp instanceof Container)
       downKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
 
-    if (forwardKeystrokes.contains (keystroke))
+    if (forwardKeystrokes.contains (eventKeystroke))
       {
         focusNextComponent (comp);
         e.consume ();
       }
-    else if (backwardKeystrokes.contains (keystroke))
+    else if (backwardKeystrokes.contains (eventKeystroke))
       {
         focusPreviousComponent (comp);
         e.consume ();
       }
-    else if (upKeystrokes.contains (keystroke))
+    else if (upKeystrokes.contains (eventKeystroke))
       {
         upFocusCycle (comp);
         e.consume ();
       }
     else if (comp instanceof Container
-             && downKeystrokes.contains (keystroke))
+             && downKeystrokes.contains (eventKeystroke))
       {
         downFocusCycle ((Container) comp);
         e.consume ();
       }
+    else if (forwardKeystrokes.contains (oppositeKeystroke)
+             || backwardKeystrokes.contains (oppositeKeystroke)
+             || upKeystrokes.contains (oppositeKeystroke)
+             || (comp instanceof Container &&
+                 downKeystrokes.contains (oppositeKeystroke)))
+      e.consume ();
   }
 
   protected void enqueueKeyEvents (long after, Component untilFocused)
@@ -397,7 +411,7 @@
     FocusTraversalPolicy policy = focusCycleRoot.getFocusTraversalPolicy ();
 
     Component previous = policy.getComponentBefore (focusCycleRoot, focusComp);
-    previous.requestFocus ();
+    previous.requestFocusInWindow ();
   }
 
   public void focusNextComponent (Component comp)
@@ -407,7 +421,7 @@
     FocusTraversalPolicy policy = focusCycleRoot.getFocusTraversalPolicy ();
 
     Component next = policy.getComponentAfter (focusCycleRoot, focusComp);
-    next.requestFocus ();
+    next.requestFocusInWindow ();
   }
 
   public void upFocusCycle (Component comp)
@@ -419,13 +433,13 @@
       {
         FocusTraversalPolicy policy = focusCycleRoot.getFocusTraversalPolicy ();
         Component defaultComponent = policy.getDefaultComponent (focusCycleRoot);
-        defaultComponent.requestFocus ();
+        defaultComponent.requestFocusInWindow ();
       }
     else
       {
         Container parentFocusCycleRoot = focusCycleRoot.getFocusCycleRootAncestor ();
 
-        focusCycleRoot.requestFocus ();
+        focusCycleRoot.requestFocusInWindow ();
         setGlobalCurrentFocusCycleRoot (parentFocusCycleRoot);
       }
   }
@@ -439,7 +453,7 @@
       {
         FocusTraversalPolicy policy = cont.getFocusTraversalPolicy ();
         Component defaultComponent = policy.getDefaultComponent (cont);
-        defaultComponent.requestFocus ();
+        defaultComponent.requestFocusInWindow ();
         setGlobalCurrentFocusCycleRoot (cont);
       }
   }
Index: java/awt/EventDispatchThread.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/awt/EventDispatchThread.java,v
retrieving revision 1.5.6.2
diff -u -r1.5.6.2 EventDispatchThread.java
--- java/awt/EventDispatchThread.java	22 Apr 2004 20:26:32 -0000	1.5.6.2
+++ java/awt/EventDispatchThread.java	7 May 2004 00:10:29 -0000
@@ -57,9 +57,6 @@
 
   public void run()
   {
-    // Set the default KeyboardFocusManager.
-    KeyboardFocusManager.setCurrentKeyboardFocusManager (null);
-
     while (true)
       {
         try
Index: jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c
===================================================================
RCS file: /cvs/gcc/gcc/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c,v
retrieving revision 1.15.2.6
diff -u -r1.15.2.6 gnu_java_awt_peer_gtk_GtkComponentPeer.c
--- jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c	22 Apr 2004 20:26:32 -0000	1.15.2.6
+++ jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c	7 May 2004 00:10:29 -0000
@@ -39,6 +39,7 @@
 #include "gtkpeer.h"
 #include "gnu_java_awt_peer_gtk_GtkComponentPeer.h"
 #include <gtk/gtkprivate.h>
+#include <gdk/gdkkeysyms.h>
 
 static GtkWidget *find_fg_color_widget (GtkWidget *widget);
 static GtkWidget *find_bg_color_widget (GtkWidget *widget);
@@ -48,6 +49,360 @@
 static gboolean focus_out_cb (GtkWidget *widget,
                               GdkEventFocus *event,
                               jobject peer);
+/*
+ * This method returns a GDK keyval that corresponds to one of the
+ * keysyms in the X keymap table.  The return value is only used to
+ * determine the keyval's corresponding hardware keycode, and doesn't
+ * reflect an accurate translation of a Java virtual key value to a
+ * GDK keyval.
+ */
+#ifdef __GNUC__
+__inline
+#endif
+static guint
+awt_keycode_to_keysym (jint keyCode, jint keyLocation)
+{
+  /* GDK_A through GDK_Z */
+  if (keyCode >= VK_A && keyCode <= VK_Z)
+    return gdk_keyval_to_lower (keyCode);
+
+  /* GDK_0 through GDK_9 */
+  if (keyCode >= VK_0 && keyCode <= VK_9)
+    return keyCode;
+
+  switch (keyCode)
+    {
+    case VK_ENTER:
+      return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Enter : GDK_Return;
+    case VK_BACK_SPACE:
+      return GDK_BackSpace;
+    case VK_TAB:
+      return GDK_Tab;
+    case VK_CANCEL:
+      return GDK_Cancel;
+    case VK_CLEAR:
+      return GDK_Clear;
+    case VK_SHIFT:
+      return keyLocation == AWT_KEY_LOCATION_LEFT ? GDK_Shift_L : GDK_Shift_R;
+    case VK_CONTROL:
+      return keyLocation == AWT_KEY_LOCATION_LEFT ? GDK_Control_L : GDK_Control_R;
+    case VK_ALT:
+      return keyLocation == AWT_KEY_LOCATION_LEFT ? GDK_Alt_L : GDK_Alt_R;
+    case VK_PAUSE:
+      return GDK_Pause;
+    case VK_CAPS_LOCK:
+      return GDK_Caps_Lock;
+    case VK_ESCAPE:
+      return GDK_Escape;
+    case VK_SPACE:
+      return GDK_space;
+    case VK_PAGE_UP:
+      return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Page_Up : GDK_Page_Up;
+    case VK_PAGE_DOWN:
+      return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Page_Down : GDK_Page_Down;
+    case VK_END:
+      return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_End : GDK_End;
+    case VK_HOME:
+      return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Home : GDK_Home;
+    case VK_LEFT:
+      return GDK_Left;
+    case VK_UP:
+      return GDK_Up;
+    case VK_RIGHT:
+      return GDK_Right;
+    case VK_DOWN:
+      return GDK_Down;
+    case VK_COMMA:
+      return GDK_comma;
+    case VK_MINUS:
+      return GDK_minus;
+    case VK_PERIOD:
+      return GDK_period;
+    case VK_SLASH:
+      return GDK_slash;
+      /*
+    case VK_0:
+    case VK_1:
+    case VK_2:
+    case VK_3:
+    case VK_4:
+    case VK_5:
+    case VK_6:
+    case VK_7:
+    case VK_8:
+    case VK_9:
+      */
+    case VK_SEMICOLON:
+      return GDK_semicolon;
+    case VK_EQUALS:
+      return GDK_equal;
+      /*
+    case VK_A:
+    case VK_B:
+    case VK_C:
+    case VK_D:
+    case VK_E:
+    case VK_F:
+    case VK_G:
+    case VK_H:
+    case VK_I:
+    case VK_J:
+    case VK_K:
+    case VK_L:
+    case VK_M:
+    case VK_N:
+    case VK_O:
+    case VK_P:
+    case VK_Q:
+    case VK_R:
+    case VK_S:
+    case VK_T:
+    case VK_U:
+    case VK_V:
+    case VK_W:
+    case VK_X:
+    case VK_Y:
+    case VK_Z:
+      */
+    case VK_OPEN_BRACKET:
+      return GDK_bracketleft;
+    case VK_BACK_SLASH:
+      return GDK_backslash;
+    case VK_CLOSE_BRACKET:
+      return GDK_bracketright;
+    case VK_NUMPAD0:
+      return GDK_KP_0;
+    case VK_NUMPAD1:
+      return GDK_KP_1;
+    case VK_NUMPAD2:
+      return GDK_KP_2;
+    case VK_NUMPAD3:
+      return GDK_KP_3;
+    case VK_NUMPAD4:
+      return GDK_KP_4;
+    case VK_NUMPAD5:
+      return GDK_KP_5;
+    case VK_NUMPAD6:
+      return GDK_KP_6;
+    case VK_NUMPAD7:
+      return GDK_KP_7;
+    case VK_NUMPAD8:
+      return GDK_KP_8;
+    case VK_NUMPAD9:
+      return GDK_KP_9;
+    case VK_MULTIPLY:
+      return GDK_KP_Multiply;
+    case VK_ADD:
+      return GDK_KP_Add;
+      /*
+    case VK_SEPARATER:
+      */
+    case VK_SEPARATOR:
+      return GDK_KP_Separator;
+    case VK_SUBTRACT:
+      return GDK_KP_Subtract;
+    case VK_DECIMAL:
+      return GDK_KP_Decimal;
+    case VK_DIVIDE:
+      return GDK_KP_Divide;
+    case VK_DELETE:
+      return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Delete : GDK_Delete;
+    case VK_NUM_LOCK:
+      return GDK_Num_Lock;
+    case VK_SCROLL_LOCK:
+      return GDK_Scroll_Lock;
+    case VK_F1:
+      return GDK_F1;
+    case VK_F2:
+      return GDK_F2;
+    case VK_F3:
+      return GDK_F3;
+    case VK_F4:
+      return GDK_F4;
+    case VK_F5:
+      return GDK_F5;
+    case VK_F6:
+      return GDK_F6;
+    case VK_F7:
+      return GDK_F7;
+    case VK_F8:
+      return GDK_F8;
+    case VK_F9:
+      return GDK_F9;
+    case VK_F10:
+      return GDK_F10;
+    case VK_F11:
+      return GDK_F11;
+    case VK_F12:
+      return GDK_F12;
+    case VK_F13:
+      return GDK_F13;
+    case VK_F14:
+      return GDK_F14;
+    case VK_F15:
+      return GDK_F15;
+    case VK_F16:
+      return GDK_F16;
+    case VK_F17:
+      return GDK_F17;
+    case VK_F18:
+      return GDK_F18;
+    case VK_F19:
+      return GDK_F19;
+    case VK_F20:
+      return GDK_F20;
+    case VK_F21:
+      return GDK_F21;
+    case VK_F22:
+      return GDK_F22;
+    case VK_F23:
+      return GDK_F23;
+    case VK_F24:
+      return GDK_F24;
+    case VK_PRINTSCREEN:
+      return GDK_Print;
+    case VK_INSERT:
+      return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Insert : GDK_Insert;
+    case VK_HELP:
+      return GDK_Help;
+    case VK_META:
+      return keyLocation == AWT_KEY_LOCATION_LEFT ? GDK_Meta_L : GDK_Meta_R;
+    case VK_BACK_QUOTE:
+      return GDK_grave;
+    case VK_QUOTE:
+      return GDK_apostrophe;
+    case VK_KP_UP:
+      return GDK_KP_Up;
+    case VK_KP_DOWN:
+      return GDK_KP_Down;
+    case VK_KP_LEFT:
+      return GDK_KP_Left;
+    case VK_KP_RIGHT:
+      return GDK_KP_Right;
+    case VK_DEAD_GRAVE:
+      return GDK_dead_grave;
+    case VK_DEAD_ACUTE:
+      return GDK_dead_acute;
+    case VK_DEAD_CIRCUMFLEX:
+      return GDK_dead_circumflex;
+    case VK_DEAD_TILDE:
+      return GDK_dead_tilde;
+    case VK_DEAD_MACRON:
+      return GDK_dead_macron;
+    case VK_DEAD_BREVE:
+      return GDK_dead_breve;
+    case VK_DEAD_ABOVEDOT:
+      return GDK_dead_abovedot;
+    case VK_DEAD_DIAERESIS:
+      return GDK_dead_diaeresis;
+    case VK_DEAD_ABOVERING:
+      return GDK_dead_abovering;
+    case VK_DEAD_DOUBLEACUTE:
+      return GDK_dead_doubleacute;
+    case VK_DEAD_CARON:
+      return GDK_dead_caron;
+    case VK_DEAD_CEDILLA:
+      return GDK_dead_cedilla;
+    case VK_DEAD_OGONEK:
+      return GDK_dead_ogonek;
+    case VK_DEAD_IOTA:
+      return GDK_dead_iota;
+    case VK_DEAD_VOICED_SOUND:
+      return GDK_dead_voiced_sound;
+    case VK_DEAD_SEMIVOICED_SOUND:
+      return GDK_dead_semivoiced_sound;
+    case VK_AMPERSAND:
+      return GDK_ampersand;
+    case VK_ASTERISK:
+      return GDK_asterisk;
+    case VK_QUOTEDBL:
+      return GDK_quotedbl;
+    case VK_LESS:
+      return GDK_less;
+    case VK_GREATER:
+      return GDK_greater;
+    case VK_BRACELEFT:
+      return GDK_braceleft;
+    case VK_BRACERIGHT:
+      return GDK_braceright;
+    case VK_AT:
+      return GDK_at;
+    case VK_COLON:
+      return GDK_colon;
+    case VK_CIRCUMFLEX:
+      return GDK_asciicircum;
+    case VK_DOLLAR:
+      return GDK_dollar;
+    case VK_EURO_SIGN:
+      return GDK_EuroSign;
+    case VK_EXCLAMATION_MARK:
+      return GDK_exclam;
+    case VK_INVERTED_EXCLAMATION_MARK:
+      return GDK_exclamdown;
+    case VK_LEFT_PARENTHESIS:
+      return GDK_parenleft;
+    case VK_NUMBER_SIGN:
+      return GDK_numbersign;
+    case VK_PLUS:
+      return GDK_plus;
+    case VK_RIGHT_PARENTHESIS:
+      return GDK_parenright;
+    case VK_UNDERSCORE:
+      return GDK_underscore;
+      /*
+    case VK_FINAL:
+    case VK_CONVERT:
+    case VK_NONCONVERT:
+    case VK_ACCEPT:
+      */
+    case VK_MODECHANGE:
+      return GDK_Mode_switch;
+      /*
+    case VK_KANA:
+      */
+    case VK_KANJI:
+      return GDK_Kanji;
+      /*
+    case VK_ALPHANUMERIC:
+      */
+    case VK_KATAKANA:
+      return GDK_Katakana;
+    case VK_HIRAGANA:
+      return GDK_Hiragana;
+      /*
+    case VK_FULL_WIDTH:
+    case VK_HALF_WIDTH:
+    case VK_ROMAN_CHARACTERS:
+    case VK_ALL_CANDIDATES:
+      */
+    case VK_PREVIOUS_CANDIDATE:
+      return GDK_PreviousCandidate;
+    case VK_CODE_INPUT:
+      return GDK_Codeinput;
+      /*
+    case VK_JAPANESE_KATAKANA:
+    case VK_JAPANESE_HIRAGANA:
+    case VK_JAPANESE_ROMAN:
+      */
+    case VK_KANA_LOCK:
+      return GDK_Kana_Lock;
+      /*
+    case VK_INPUT_METHOD_ON_OFF:
+    case VK_CUT:
+    case VK_COPY:
+    case VK_PASTE:
+    case VK_UNDO:
+    case VK_AGAIN:
+    case VK_FIND:
+    case VK_PROPS:
+    case VK_STOP:
+    case VK_COMPOSE:
+    case VK_ALT_GRAPH:
+      */
+    default:
+      return GDK_VoidSymbol;
+    }
+}
 
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkGenericPeer_dispose
   (JNIEnv *env, jobject obj)
@@ -134,7 +489,8 @@
   gdk_threads_leave ();
 }
 
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetRequestFocus
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetRequestFocus
   (JNIEnv *env, jobject obj)
 {
   void *ptr;
@@ -156,43 +512,115 @@
    jint keyCode, jchar keyChar, jint keyLocation)
 {
   void *ptr;
-  GdkEvent *event = gdk_event_new (GDK_MOTION_NOTIFY);
+  GdkEvent *event = NULL;
+  GdkEventKey *keyevent = NULL;
+  GdkKeymapKey *keymap_keys = NULL;
+  gint n_keys = 0;
+  gint level = 0;
+  guint lookup_keyval = 0;
+  GdkModifierType consumed_modifiers;
 
   ptr = NSA_GET_PTR (env, obj);
 
-  /* FIXME: need to flesh this out. */
-  /* Translate */
+  gdk_threads_enter ();
+
   if (id == AWT_KEY_PRESSED)
-    event->type = GDK_KEY_PRESS;
+    event = gdk_event_new (GDK_KEY_PRESS);
   else if (id == AWT_KEY_RELEASED)
-    event->type = GDK_KEY_RELEASE;
+    event = gdk_event_new (GDK_KEY_RELEASE);
   else
-    /* Don't send AWT KEY_TYPED events to GTK. */
-    return;
+    {
+      gdk_threads_leave ();
+      /* Don't send AWT KEY_TYPED events to GTK. */
+      return;
+    }
 
-  /* FIXME: this won't work for TextAreas or Lists, which are packed
-     in GtkScrolledWindows. */
   if (GTK_IS_BUTTON (ptr))
     event->key.window = GTK_BUTTON (ptr)->event_window;
+  else if (GTK_IS_SCROLLED_WINDOW (ptr))
+    event->key.window = GTK_WIDGET (GTK_SCROLLED_WINDOW (ptr)->container.child)->window;
   else
     event->key.window = GTK_WIDGET (ptr)->window;
 
-  event->key.send_event = TRUE;
-
+  event->key.send_event = 0;
   event->key.time = (guint32) when;
-  /* Translate state */
-  event->key.state = 0;
-  /* Translate keyval */
-  event->key.keyval = keyCode;
-  event->key.length = 1;
-  /* Translate keyChar */
-  event->key.string = g_strdup ("a");
-  event->key.hardware_keycode = 0;
-  event->key.group = 0;
 
-  gdk_threads_enter ();
+  if (mods & AWT_SHIFT_MASK)
+    event->key.state |= GDK_SHIFT_MASK;
+  if (mods & AWT_CTRL_MASK)
+    event->key.state |= GDK_CONTROL_MASK;
+  if (mods & AWT_ALT_MASK)
+    event->key.state |= GDK_MOD1_MASK;
+
+  /* This hack is needed because the AWT has no notion of num lock.
+     It infers numlock state from the only Java virtual keys that are
+     affected by it. */
+  if (keyCode == VK_NUMPAD9
+      || keyCode == VK_NUMPAD8
+      || keyCode == VK_NUMPAD7
+      || keyCode == VK_NUMPAD6
+      || keyCode == VK_NUMPAD5
+      || keyCode == VK_NUMPAD4
+      || keyCode == VK_NUMPAD3
+      || keyCode == VK_NUMPAD2
+      || keyCode == VK_NUMPAD1
+      || keyCode == VK_NUMPAD0
+      || keyCode == VK_DECIMAL)
+    event->key.state |= GDK_MOD2_MASK;
+
+  /* These values don't need to be filled in since GTK doesn't use
+     them. */
+  event->key.length = 0;
+  event->key.string = NULL;
+
+  lookup_keyval = awt_keycode_to_keysym (keyCode, keyLocation);
+
+  if (!gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (),
+                                          lookup_keyval,
+                                          &keymap_keys,
+                                          &n_keys))
+    {
+      /* No matching keymap entry was found. */
+      g_printerr ("No matching keymap entries were found\n");
+      gdk_threads_leave ();
+      return;
+    }
+
+  if (n_keys > 1)
+    g_printerr ("warning: using hardware keycode from first keymap entry, though multiple entries were found\n");
+
+  event->key.hardware_keycode = keymap_keys[0].keycode;
+  event->key.group =  keymap_keys[0].group;
+
+  g_free (keymap_keys);
 
-  gtk_main_do_event (event);
+  if (!gdk_keymap_translate_keyboard_state (gdk_keymap_get_default (),
+                                            event->key.hardware_keycode,
+                                            event->key.state,
+                                            event->key.group,
+                                            &event->key.keyval,
+                                            &event->key.group,
+                                            &level,
+                                            &consumed_modifiers))
+    {
+      /* No matching keyval was found. */
+      g_printerr ("No matching keyval was found\n");
+      gdk_threads_leave ();
+      return;
+    }
+
+  /*  keyevent = (GdkEventKey *) event; */
+  /*  g_printerr ("generated event: sent: %d  time: %d  state: %d  keyval: %d  length: %d  string: %s  hardware_keycode: %d  group: %d\n", keyevent->send_event, keyevent->time, keyevent->state, keyevent->keyval, keyevent->length, keyevent->string, keyevent->hardware_keycode, keyevent->group); */
+
+  /* We already received the original key event on the window itself,
+     so we don't want to resend it. */
+  if (!GTK_IS_WINDOW (ptr))
+    {
+      if (GTK_IS_SCROLLED_WINDOW (ptr))
+        gtk_widget_event (GTK_WIDGET (GTK_SCROLLED_WINDOW (ptr)->container.child), event);
+      else
+        gtk_widget_event (GTK_WIDGET (ptr), event);
+    }
 
   gdk_threads_leave ();
 }
Index: jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c
===================================================================
RCS file: /cvs/gcc/gcc/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c,v
retrieving revision 1.19.2.4
diff -u -r1.19.2.4 gnu_java_awt_peer_gtk_GtkEvents.c
--- jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c	22 Apr 2004 20:26:32 -0000	1.19.2.4
+++ jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c	7 May 2004 00:10:29 -0000
@@ -1066,6 +1066,9 @@
     case GDK_KEY_PRESS:
         if (GTK_IS_WINDOW (widget))
           {
+            /*            GdkEventKey *keyevent = (GdkEventKey *) event; */
+            /*            g_printerr ("key press event: sent: %d  time: %d  state: %d  keyval: %d  length: %d  string: %s  hardware_keycode: %d  group: %d\n", keyevent->send_event, keyevent->time, keyevent->state, keyevent->keyval, keyevent->length, keyevent->string, keyevent->hardware_keycode, keyevent->group); */
+
             (*gdk_env)->CallVoidMethod (gdk_env, peer,
                                         postKeyEventID,
                                         (jint) AWT_KEY_PRESSED,
@@ -1074,6 +1077,11 @@
                                         keysym_to_awt_keycode (event),
                                         keyevent_to_awt_keychar (event),
                                         keysym_to_awt_keylocation (event));
+            /* FIXME: generation of key typed events needs to be moved
+               to GtkComponentPeer.postKeyEvent.  If the key in a key
+               press event is not an "action" key
+               (KeyEvent.isActionKey) and is not a modifier key, then
+               it should generate a key typed event. */
             return TRUE;
           }
         else
@@ -1093,12 +1101,7 @@
             return TRUE;
         }
       else
-        {
-          /* We generated this event after Java processed the
-             corresponding event on the window. */
-          if (event->key.send_event)
-            return FALSE;
-        }
+        return FALSE;
       break;
     default:
       break;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]