Index: gnu/java/awt/peer/gtk/GtkComponentPeer.java =================================================================== RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java,v retrieving revision 1.58 diff -u -r1.58 GtkComponentPeer.java --- gnu/java/awt/peer/gtk/GtkComponentPeer.java 20 Jan 2004 21:31:58 -0000 1.58 +++ gnu/java/awt/peer/gtk/GtkComponentPeer.java 27 Jan 2004 15:59:11 -0000 @@ -91,6 +91,9 @@ 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 gtkWidgetQueueDrawArea(int x, int y, int width, int height); + native void addExposeFilter(); + native void removeExposeFilter(); void create () { @@ -207,6 +210,37 @@ public void handleEvent (AWTEvent event) { + int id = event.getID(); + + switch (id) + { + case PaintEvent.PAINT: + case PaintEvent.UPDATE: + { + try + { + Graphics g = getGraphics (); + + // Some peers like GtkFileDialogPeer are repainted by Gtk itself + if (g == null) + break; + + g.setClip (((PaintEvent)event).getUpdateRect()); + + if (id == PaintEvent.PAINT) + awtComponent.paint (g); + else + awtComponent.update (g); + + g.dispose (); + } + catch (InternalError e) + { + System.err.println (e); + } + } + break; + } } public boolean isFocusTraversable () @@ -225,7 +259,21 @@ public void paint (Graphics g) { - awtComponent.paint (g); + Component parent = awtComponent.getParent(); + GtkComponentPeer parentPeer = null; + if ((parent instanceof Container) && !parent.isLightweight()) + parentPeer = (GtkComponentPeer) parent.getPeer(); + + addExposeFilter(); + if (parentPeer != null) + parentPeer.addExposeFilter(); + + Rectangle clip = g.getClipBounds(); + gtkWidgetQueueDrawArea(clip.x, clip.y, clip.width, clip.height); + + removeExposeFilter(); + if (parentPeer != null) + parentPeer.removeExposeFilter(); } public Dimension preferredSize () Index: gnu/java/awt/peer/gtk/GtkContainerPeer.java =================================================================== RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/GtkContainerPeer.java,v retrieving revision 1.21 diff -u -r1.21 GtkContainerPeer.java --- gnu/java/awt/peer/gtk/GtkContainerPeer.java 13 Jan 2004 21:30:47 -0000 1.21 +++ gnu/java/awt/peer/gtk/GtkContainerPeer.java 27 Jan 2004 15:59:11 -0000 @@ -100,41 +100,6 @@ return new GdkGraphics (this); } - public void handleEvent (AWTEvent event) - { - int id = event.getID(); - - switch (id) - { - case PaintEvent.PAINT: - case PaintEvent.UPDATE: - { - try - { - Graphics g = getGraphics (); - - // Some peers like GtkFileDialogPeer are repainted by Gtk itself - if (g == null) - break; - - g.setClip (((PaintEvent)event).getUpdateRect()); - - if (id == PaintEvent.PAINT) - awtComponent.paint (g); - else - awtComponent.update (g); - - g.dispose (); - } - catch (InternalError e) - { - System.err.println (e); - } - } - break; - } - } - public void beginLayout () { } public void endLayout () { } public boolean isPaintPending () { return false; } Index: include/gnu_java_awt_peer_gtk_GtkComponentPeer.h =================================================================== RCS file: /cvsroot/classpath/classpath/include/gnu_java_awt_peer_gtk_GtkComponentPeer.h,v retrieving revision 1.7 diff -u -r1.7 gnu_java_awt_peer_gtk_GtkComponentPeer.h --- include/gnu_java_awt_peer_gtk_GtkComponentPeer.h 7 Jan 2004 02:23:37 -0000 1.7 +++ include/gnu_java_awt_peer_gtk_GtkComponentPeer.h 27 Jan 2004 15:59:11 -0000 @@ -21,6 +21,9 @@ extern JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetCursor (JNIEnv *env, jobject, jint); extern JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetBackground (JNIEnv *env, jobject, jint, jint, jint); extern JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetForeground (JNIEnv *env, jobject, jint, jint, jint); +extern JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetQueueDrawArea (JNIEnv *env, jobject, jint, jint, jint, jint); +extern JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_addExposeFilter (JNIEnv *env, jobject); +extern JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_removeExposeFilter (JNIEnv *env, jobject); extern JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_connectJObject (JNIEnv *env, jobject); extern JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_connectSignals (JNIEnv *env, jobject); extern JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_requestFocus__ (JNIEnv *env, jobject); Index: java/awt/Component.java =================================================================== RCS file: /cvsroot/classpath/classpath/java/awt/Component.java,v retrieving revision 1.25 diff -u -r1.25 Component.java --- java/awt/Component.java 27 Jan 2004 09:46:25 -0000 1.25 +++ java/awt/Component.java 27 Jan 2004 15:59:11 -0000 @@ -1702,6 +1702,9 @@ */ public void paint(Graphics g) { + // Paint the heavyweight peer + if (!isLightweight() && peer != null) + peer.paint(g); } /** @@ -1719,6 +1722,15 @@ */ public void update(Graphics g) { + if (!isLightweight()) + { + Rectangle clip = g.getClipBounds(); + if (clip == null) + g.clearRect(0, 0, width, height); + else + g.clearRect(clip.x, clip.y, clip.width, clip.height); + } + paint(g); } @@ -1732,8 +1744,6 @@ { if (! visible) return; - if (peer != null) - peer.paint(g); paint(g); } @@ -2787,8 +2797,6 @@ if (e instanceof FocusEvent) processFocusEvent((FocusEvent) e); - else if (e instanceof PaintEvent) - processPaintEvent((PaintEvent) e); else if (e instanceof MouseWheelEvent) processMouseWheelEvent((MouseWheelEvent) e); else if (e instanceof MouseEvent) @@ -4222,42 +4230,6 @@ newEvent.setUpdateRect(union); return newEvent; - } - - /** - * Does the work for a paint event. - * - * @param event the event to process - */ - private void processPaintEvent(PaintEvent event) - { - // Can't do graphics without peer - if (peer == null) - return; - - Graphics gfx = getGraphics(); - try - { - Shape clip = event.getUpdateRect(); - gfx.setClip(clip); - - switch (event.id) - { - case PaintEvent.PAINT: - paint(gfx); - break; - case PaintEvent.UPDATE: - update(gfx); - break; - default: - throw new IllegalArgumentException("unknown paint event"); - } - event.consume (); - } - finally - { - gfx.dispose(); - } } /** Index: java/awt/Container.java =================================================================== RCS file: /cvsroot/classpath/classpath/java/awt/Container.java,v retrieving revision 1.27 diff -u -r1.27 Container.java --- java/awt/Container.java 21 Jan 2004 15:14:23 -0000 1.27 +++ java/awt/Container.java 27 Jan 2004 15:59:13 -0000 @@ -663,8 +663,9 @@ { if (!isShowing()) return; - super.paint(g); - visitChildren(g, GfxPaintVisitor.INSTANCE, true); + // Visit heavyweights as well, in case they were + // erased when we cleared the background for this container. + visitChildren(g, GfxPaintVisitor.INSTANCE, false); } /** @@ -678,11 +679,6 @@ */ public void update(Graphics g) { - Rectangle clip = g.getClipBounds(); - if (clip == null) - g.clearRect(0, 0, width, height); - else - g.clearRect(clip.x, clip.y, clip.width, clip.height); super.update(g); } @@ -1204,8 +1200,12 @@ for (int i = ncomponents - 1; i >= 0; --i) { Component comp = component[i]; + // If we're visiting heavyweights as well, + // don't recurse into Containers here. This avoids + // painting the same nested child multiple times. boolean applicable = comp.isVisible() - && (comp.isLightweight() || !lightweightOnly); + && (comp.isLightweight() + || !lightweightOnly && ! (comp instanceof Container)); if (applicable) visitChild(gfx, visitor, comp); Index: native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c =================================================================== RCS file: /cvsroot/classpath/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c,v retrieving revision 1.17 diff -u -r1.17 gnu_java_awt_peer_gtk_GtkComponentPeer.c --- native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c 26 Jan 2004 21:20:12 -0000 1.17 +++ native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c 27 Jan 2004 15:59:13 -0000 @@ -575,6 +575,80 @@ (*env)->ReleaseStringUTFChars (env, jname, name); } +gboolean +filter_expose_event_handler (GtkWidget *widget, GdkEvent *event, jobject peer) +{ + // Prevent the default event handler from getting this signal if applicable + // FIXME: I came up with these filters by looking for patterns in the unwanted + // expose events that are fed back to us from gtk/X. Perhaps there is + // a way to prevent them from occuring in the first place. + if (event->type == GDK_EXPOSE && (!GTK_IS_LAYOUT(widget) + || event->any.window != widget->window)) + { + g_signal_stop_emission_by_name(GTK_OBJECT(widget), "event"); + return FALSE; + } + else + { + // There may be non-expose events that are triggered while we're + // painting a heavyweight peer. + return pre_event_handler(widget, event, peer); + } +} + +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_addExposeFilter + (JNIEnv *env, jobject obj) +{ + void *ptr = NSA_GET_PTR (env, obj); + jobject *gref = NSA_GET_GLOBAL_REF (env, obj); + g_assert (gref); + + gdk_threads_enter (); + + g_signal_handlers_block_by_func (GTK_OBJECT(ptr), *pre_event_handler, *gref); + g_signal_connect( GTK_OBJECT(ptr), "event", + G_CALLBACK(filter_expose_event_handler), *gref); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_removeExposeFilter + (JNIEnv *env, jobject obj) +{ + void *ptr = NSA_GET_PTR (env, obj); + jobject *gref = NSA_GET_GLOBAL_REF (env, obj); + g_assert (gref); + + gdk_threads_enter (); + + g_signal_handlers_disconnect_by_func (GTK_OBJECT(ptr), + *filter_expose_event_handler, *gref); + g_signal_handlers_unblock_by_func (GTK_OBJECT(ptr), *pre_event_handler, *gref); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetQueueDrawArea + (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height) +{ + GdkRectangle rect; + void *ptr; + + ptr = NSA_GET_PTR (env, obj); + + rect.x = x + GTK_WIDGET(ptr)->allocation.x; + rect.y = y + GTK_WIDGET(ptr)->allocation.y; + rect.width = width; + rect.height = height; + + gdk_threads_enter (); + + gdk_window_invalidate_rect (GTK_WIDGET (ptr)->window, &rect, 0); + gdk_window_process_all_updates(); + + gdk_threads_leave (); +} + JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_connectJObject (JNIEnv *env, jobject obj) { Index: native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c =================================================================== RCS file: /cvsroot/classpath/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c,v retrieving revision 1.20 diff -u -r1.20 gnu_java_awt_peer_gtk_GtkEvents.c --- native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c 26 Jan 2004 16:22:22 -0000 1.20 +++ native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c 27 Jan 2004 15:59:13 -0000 @@ -1012,12 +1012,21 @@ break; case GDK_EXPOSE: { - (*gdk_env)->CallVoidMethod (gdk_env, peer, - postExposeEventID, - (jint)event->expose.area.x, - (jint)event->expose.area.y, - (jint)event->expose.area.width, - (jint)event->expose.area.height); + // This filters out unwanted feedback expose events from gtk/X + // when we explictly invalidate and update heavyweight components, + // thus avoiding an infinite loop. + // FIXME: I'm not quite sure why we're getting these expose events. + // Maybe there is a way to avoid them? + if((event->any.window == widget->window && event->any.send_event) + || GTK_IS_LAYOUT(widget)) + { + (*gdk_env)->CallVoidMethod (gdk_env, peer, + postExposeEventID, + (jint)event->expose.area.x, + (jint)event->expose.area.y, + (jint)event->expose.area.width, + (jint)event->expose.area.height); + } } break; case GDK_FOCUS_CHANGE: