This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
Patch: More TextComponent fixes
- From: Thomas Fitzsimmons <fitzsim at redhat dot com>
- To: "java-patches at gcc dot gnu dot org" <java-patches at gcc dot gnu dot org>
- Date: 10 Jul 2003 20:54:09 -0400
- Subject: 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