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]

Patch: More TextComponent fixes


Hello,

This patch improves KeyEvent generation, and fixes some problems with
the AWT TextComponents.  With this patch, the text components can listen
for key events, including KEY_TYPED events.

It made most sense to trigger KEY_TYPED events in response to the text
widgets' IMContext "commit" signals.  Doing so allows the user to input
any Unicode character using any input method available on the widget. 
The downside to this approach is that it discards some event
information.  However, that information is likely not very useful in
general.

Please review and comment.

Thanks,
Tom

2003-07-10  Thomas Fitzsimmons  <fitzsim@redhat.com>

	* gnu/java/awt/peer/gtk/GtkTextComponentPeer.java
	(connectHooks): New method.
	(handleEvent): Remove.
	* gnu/java/awt/peer/gtk/GtkTextFieldPeer.java
	(createHooks): Remove declaration.
	* jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c
	(generates_key_typed_event): Change to handle only certain
	keyvals.
	(awt_event_handler): Add special handling for GtkTextView.
	* jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextComponentPeer.c
	(textcomponent_commit_cb): New function.
	(textcomponent_changed_cb): Likewise.
	* jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextFieldPeer.c
	(connectHooks): Wrap in ifdef 0.

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.3
diff -u -b -B -r1.3 GtkComponentPeer.java
Index: gnu/java/awt/peer/gtk/GtkTextComponentPeer.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/awt/peer/gtk/GtkTextComponentPeer.java,v
retrieving revision 1.3
diff -u -b -B -r1.3 GtkTextComponentPeer.java
--- gnu/java/awt/peer/gtk/GtkTextComponentPeer.java	7 Jul 2003 19:56:03 -0000	1.3
+++ gnu/java/awt/peer/gtk/GtkTextComponentPeer.java	10 Jul 2003 23:29:57 -0000
@@ -51,6 +51,7 @@
     setText (tc.getText ());
   }
   
+  public native void connectHooks ();
   public native int getCaretPosition ();
   public native void setCaretPosition (int pos);
   public native int getSelectionStart ();
@@ -78,17 +79,5 @@
   protected void postTextEvent ()
   {
     q.postEvent (new TextEvent (awtComponent, TextEvent.TEXT_VALUE_CHANGED));
-  }
-
-  public void handleEvent (AWTEvent e)
-  {
-    if (e.getID () == KeyEvent.KEY_TYPED
-        && ((TextComponent)e.getSource()).isEditable())
-      {
-        KeyEvent ke = (KeyEvent)e;
-
-        if (!ke.isConsumed())
-          postTextEvent ();
-      }
   }
 }
Index: gnu/java/awt/peer/gtk/GtkTextFieldPeer.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java,v
retrieving revision 1.3
diff -u -b -B -r1.3 GtkTextFieldPeer.java
--- gnu/java/awt/peer/gtk/GtkTextFieldPeer.java	7 Jul 2003 19:56:03 -0000	1.3
+++ gnu/java/awt/peer/gtk/GtkTextFieldPeer.java	10 Jul 2003 23:29:57 -0000
@@ -48,7 +48,7 @@
 //    native void create (ComponentPeer parent, String text);
 
   native void create ();
-  native void createHooks ();
+  // native void connectHooks ();
 
   native void gtkEntryGetSize (int cols, int dims[]);
 
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.2
diff -u -b -B -r1.2 gnu_java_awt_peer_gtk_GtkComponentPeer.c
--- jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c	30 Jun 2003 23:53:29 -0000	1.2
+++ jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c	10 Jul 2003 23:30:18 -0000
@@ -639,13 +639,13 @@
   gtk_widget_realize (GTK_WIDGET (ptr));
   if(GTK_IS_BUTTON(ptr))
     {
-      g_print("-- connecting a button --\n");
+      /* g_print("-- connecting a button --\n"); */
       connect_awt_hook (env, obj, 1, GTK_BUTTON(ptr)->event_window);
     }
   else
     {
   connect_awt_hook (env, obj, 1, GTK_WIDGET (ptr)->window);
-      g_print("Connection object %p with window %p (but ptr is %p)\n", obj, GTK_WIDGET(ptr)->window, ptr);
+      /* g_print("Connection object %p with window %p (but ptr is %p)\n", obj, GTK_WIDGET(ptr)->window, ptr); */
     }
   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.3
diff -u -b -B -r1.3 gnu_java_awt_peer_gtk_GtkEvents.c
--- jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c	7 Jul 2003 19:56:04 -0000	1.3
+++ jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c	10 Jul 2003 23:30:18 -0000
@@ -232,22 +232,18 @@
     }
 }
 
+/* Checks if keyval triggers a KEY_TYPED event on the source widget.
+   This function identifies special keyvals that don't trigger
+   GtkIMContext "commit" signals, but that do trigger Java KEY_TYPED
+   events. */
 static int
-generates_key_typed_event (guint keyval)
+generates_key_typed_event (guint keyval, GtkWidget *source)
 {
-  guint vk;
-
-  vk = gdk_keyval_to_upper (keyval);
-
-  if ((vk >= 0x20 && vk <= 0x7e)	/* Most printable keysyms on a
-                                           standard US keyboard. */
-      || (vk >= 0xFF9F && vk <= 0xFFB9) /* Numeric Keypad keysyms. */
-      || vk == GDK_BackSpace
-      || vk == GDK_Delete
-      || vk == GDK_Return)
-    return 1;
-  else
-    return 0;
+  return (keyval == GDK_BackSpace
+          || keyval == GDK_Delete
+          || keyval == GDK_Return
+          || (keyval == GDK_Tab
+              && GTK_IS_TEXT_VIEW(source))) ? 1 : 0;
 }
 
 void
@@ -465,6 +461,8 @@
 	  {
 	    GtkWidget *widget;
 	    GtkWindow *window;
+            /* The window to which the Java peer is attached. */
+            GdkWindow *obj_window;
 
 	    gdk_window_get_user_data (event->any.window, (void **) &widget);
 
@@ -477,7 +475,16 @@
 		&& window->focus_widget->window)
 	      {
 		gtk_widget_activate (window->focus_widget);
-		gdk_property_get (window->focus_widget->window,
+
+                /* TextArea peers are attached to the scrolled window
+                   that contains the GtkTextView, not to the text view
+                   itself. */
+                if (GTK_IS_TEXT_VIEW (window->focus_widget))
+                  obj_window = gtk_widget_get_parent (window->focus_widget)->window;
+                else
+                  obj_window = window->focus_widget->window;
+
+		gdk_property_get (obj_window,
 				  gdk_atom_intern ("_GNU_GTKAWT_ADDR", FALSE),
 				  gdk_atom_intern ("CARDINAL", FALSE),
 				  0,
@@ -500,15 +507,16 @@
 					    event->key.string[0] : 
 					    AWT_KEY_CHAR_UNDEFINED);
 
-		if (event->key.length
-                    && generates_key_typed_event(event->key.keyval))
+                if (generates_key_typed_event (event->key.keyval, window->focus_widget))
 		  (*gdk_env)->CallVoidMethod (gdk_env, *obj_ptr,
 					      postKeyEventID,
 					      (jint) AWT_KEY_TYPED,
 					      (jlong) event->key.time,
                                               state_to_awt_mods (event->key.state),
 					      VK_UNDEFINED,
-					      (jchar) event->key.string[0]);
+                                              (jchar) (event->key.length) ?
+                                              event->key.string[0] :
+                                              AWT_KEY_CHAR_UNDEFINED);
 	      }
 	  }
 	  break;
@@ -516,6 +524,7 @@
 	  {
 	    GtkWidget *widget;
 	    GtkWindow *window;
+            GdkWindow *obj_window;
 
 	    gdk_window_get_user_data (event->any.window, (void **) &widget);
 
@@ -528,7 +537,13 @@
 		&& window->focus_widget->window)
 	      {
 		gtk_widget_activate (window->focus_widget);
-		gdk_property_get (window->focus_widget->window,
+
+                if (GTK_IS_TEXT_VIEW (window->focus_widget))
+                  obj_window = gtk_widget_get_parent (window->focus_widget)->window;
+                else
+                  obj_window = window->focus_widget->window;
+
+		gdk_property_get (obj_window,
 				  gdk_atom_intern ("_GNU_GTKAWT_ADDR", FALSE),
 				  gdk_atom_intern ("CARDINAL", FALSE),
 				  0,
Index: jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextAreaPeer.c
===================================================================
RCS file: /cvs/gcc/gcc/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextAreaPeer.c,v
retrieving revision 1.3
diff -u -b -B -r1.3 gnu_java_awt_peer_gtk_GtkTextAreaPeer.c
Index: jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextComponentPeer.c
===================================================================
RCS file: /cvs/gcc/gcc/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextComponentPeer.c,v
retrieving revision 1.3
diff -u -b -B -r1.3 gnu_java_awt_peer_gtk_GtkTextComponentPeer.c
--- jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextComponentPeer.c	7 Jul 2003 19:56:04 -0000	1.3
+++ jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextComponentPeer.c	10 Jul 2003 23:30:18 -0000
@@ -39,6 +39,62 @@
 #include "gtkpeer.h"
 #include "gnu_java_awt_peer_gtk_GtkTextComponentPeer.h"
 
+static void textcomponent_commit_cb (GtkIMContext *context,
+                                 const gchar  *str,
+                                 jobject peer);
+
+static void textcomponent_changed_cb (GtkEditable *editable,
+                                  jobject peer);
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkTextComponentPeer_connectHooks
+  (JNIEnv *env, jobject obj)
+{
+  void *ptr;
+  GtkTextView *text = NULL;
+  GtkTextBuffer *buf;
+
+  ptr = NSA_GET_PTR (env, obj);
+
+  gdk_threads_enter ();
+
+  if (GTK_IS_ENTRY(ptr))
+    {
+      g_signal_connect (GTK_ENTRY (ptr)->im_context, "commit",
+                        G_CALLBACK (textcomponent_commit_cb), obj);
+
+      g_signal_connect (GTK_EDITABLE (ptr), "changed",
+                        G_CALLBACK (textcomponent_changed_cb), obj);
+    }
+  else
+    {
+      if (GTK_IS_SCROLLED_WINDOW (ptr))
+	{
+          text = GTK_TEXT_VIEW (GTK_SCROLLED_WINDOW (ptr)->container.child);
+	}
+      else if (GTK_IS_TEXT_VIEW (ptr))
+	{
+	  text = GTK_TEXT_VIEW (ptr);
+	}
+
+      if (text)
+	{
+          g_signal_connect (text->im_context, "commit",
+                            G_CALLBACK (textcomponent_commit_cb), obj);
+
+          buf = gtk_text_view_get_buffer (text);
+          if (buf)
+            g_signal_connect (buf, "changed",
+                              G_CALLBACK (textcomponent_changed_cb), obj);
+	}
+    }
+
+  gdk_threads_leave ();
+
+  /* Connect the superclass hooks.  */
+  Java_gnu_java_awt_peer_gtk_GtkComponentPeer_connectHooks (env, obj);
+}
+
 JNIEXPORT jint JNICALL 
 Java_gnu_java_awt_peer_gtk_GtkTextComponentPeer_getCaretPosition
   (JNIEnv *env, jobject obj)
@@ -371,18 +427,6 @@
   if (GTK_IS_EDITABLE (ptr))
     {
       gtk_entry_set_text (GTK_ENTRY (ptr), str);
-
-      if (gdk_property_get (GTK_WIDGET(ptr)->window,
-                            gdk_atom_intern ("_GNU_GTKAWT_ADDR", FALSE),
-                            gdk_atom_intern ("CARDINAL", FALSE),
-                            0,
-                            sizeof (jobject),
-                            FALSE,
-                            NULL,
-                            NULL,
-                            NULL,
-                            (guchar **)&obj_ptr))
-        (*gdk_env)->CallVoidMethod (gdk_env, *obj_ptr, postTextEventID);
     }
   else
     {
@@ -405,4 +449,35 @@
   gdk_threads_leave ();
 
   (*env)->ReleaseStringUTFChars (env, contents, str);
+}
+
+static void
+textcomponent_commit_cb (GtkIMContext *context,
+                         const gchar  *str,
+                         jobject peer)
+{
+  /* str is a \0-terminated UTF-8 encoded character. */
+  gunichar2 *jc = g_utf8_to_utf16 (str, -1, NULL, NULL, NULL);
+
+  if (jc)
+    (*gdk_env)->CallVoidMethod (gdk_env, peer,
+                                postKeyEventID,
+                                (jint) AWT_KEY_TYPED,
+                                /* We don't have access to the event
+                                   that caused this commit signal to
+                                   be fired.  So approximate the event
+                                   time... */
+                                (jlong) gdk_event_get_time (NULL),
+                                /* ... and assume no modifiers. */
+                                0,
+                                VK_UNDEFINED,
+                                (jchar) jc[0]);
+  g_free (jc);
+}
+
+static void
+textcomponent_changed_cb (GtkEditable *editable,
+                      jobject peer)
+{
+  (*gdk_env)->CallVoidMethod (gdk_env, peer, postTextEventID);
 }
Index: jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextFieldPeer.c
===================================================================
RCS file: /cvs/gcc/gcc/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextFieldPeer.c,v
retrieving revision 1.3
diff -u -b -B -r1.3 gnu_java_awt_peer_gtk_GtkTextFieldPeer.c
--- jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextFieldPeer.c	30 Jun 2003 23:53:29 -0000	1.3
+++ jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextFieldPeer.c	10 Jul 2003 23:30:18 -0000
@@ -52,6 +52,7 @@
   NSA_SET_PTR (env, obj, widget);
 }
 
+#if 0
 JNIEXPORT void JNICALL 
 Java_gnu_java_awt_peer_gtk_GtkTextFieldPeer_connectHooks
   (JNIEnv *env, jobject obj)
@@ -67,6 +70,7 @@
 		    GTK_ENTRY (ptr)->text_area);
   gdk_threads_leave ();
 }
+#endif
 
 JNIEXPORT void JNICALL 
 Java_gnu_java_awt_peer_gtk_GtkTextFieldPeer_gtkEntryGetSize

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