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: Generate window events


Hello,

This patch implements window event generation for the GTK peers.  It
also fixes some related problems in the Window class.

Comments?

Tom

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

	* gnu/java/awt/peer/gtk/GtkDialogPeer.java (handleEvent):
	Remove method.
	* gnu/java/awt/peer/gtk/GtkWindowPeer.java (postWindowEvent):
	New method.
	* java/awt/Window.java (Window(Window,GraphicsConfiguration),
	show, hide, dispose, getOwnedWindows): Synchronize on tree lock.
	(dispose): Post WINDOW_CLOSED event.
	(addWindowFocusListener, addWindowStateListener): Assign result
	of multicaster add back to window listener.
	(removeWindowFocusListener, removeWindowStateListener): Assign
	result of multicaster remove back to window listener.
	(dispatchEventImpl): Add null checks for focus and state
	listeners.
	(processWindowEvent): Handle case where windowListener is null
	but state or focus listeners exist.
	* jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMainThread.c: Add JNI
	glue for postWindowEvent.
	* jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c
	(window_delete_cb, window_destroy_cb, window_show_cb,
	window_focus_in_cb, window_focus_out_cb, window_window_state_cb,
	window_get_new_state): New functions.
	* jni/gtk-peer/gtkpeer.h: Define window event and frame state
	macros.  Declare postWindowEventID.

Index: gnu/java/awt/peer/gtk/GtkDialogPeer.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/awt/peer/gtk/GtkDialogPeer.java,v
retrieving revision 1.7
diff -u -r1.7 GtkDialogPeer.java
--- gnu/java/awt/peer/gtk/GtkDialogPeer.java	9 Oct 2003 00:26:29 -0000	1.7
+++ gnu/java/awt/peer/gtk/GtkDialogPeer.java	23 Oct 2003 22:04:42 -0000
@@ -80,13 +80,4 @@
     args.add ("allow_shrink", dialog.isResizable ());
     args.add ("allow_grow", dialog.isResizable ());
   }
-
-  public void handleEvent (AWTEvent event)
-  {
-//     int id = event.getID();
-    
-//     if (id == WindowEvent.WINDOW_CLOSING)
-//       System.out.println ("got a closing event");
-  }
-
 }
Index: gnu/java/awt/peer/gtk/GtkWindowPeer.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/awt/peer/gtk/GtkWindowPeer.java,v
retrieving revision 1.7
diff -u -r1.7 GtkWindowPeer.java
--- gnu/java/awt/peer/gtk/GtkWindowPeer.java	9 Oct 2003 00:26:29 -0000	1.7
+++ gnu/java/awt/peer/gtk/GtkWindowPeer.java	23 Oct 2003 22:04:42 -0000
@@ -42,6 +42,8 @@
 import java.awt.Dimension;
 import java.awt.Insets;
 import java.awt.Window;
+import java.awt.Frame;
+import java.awt.event.WindowEvent;
 import java.awt.peer.WindowPeer;
 
 public class GtkWindowPeer extends GtkContainerPeer
@@ -56,6 +58,9 @@
   static protected final int GDK_WINDOW_TYPE_HINT_DOCK = 6;
   static protected final int GDK_WINDOW_TYPE_HINT_DESKTOP = 7;
 
+  private boolean hasBeenShown = false;
+  private int oldState = Frame.NORMAL;
+
   // Unfortunately, X does not provide a clean way to calculate the
   // dimensions of a window's borders before it has been displayed.
   // So when creating the application's first window we guess the
@@ -210,5 +215,30 @@
 		 awtComponent.getWidth(),
 		 awtComponent.getHeight());
     nativeSetVisible (b);
+  }
+
+  void postWindowEvent (int id, Window opposite, int newState)
+  {
+    if (id == WindowEvent.WINDOW_OPENED)
+      {
+	// Post a WINDOW_OPENED event the first time this window is shown.
+	if (!hasBeenShown)
+	  {
+	    q.postEvent (new WindowEvent ((Window) awtComponent, id,
+					  opposite));
+	    hasBeenShown = true;
+	  }
+      }
+    else if (id == WindowEvent.WINDOW_STATE_CHANGED)
+      {
+	if (oldState != newState)
+	  {
+	    q.postEvent (new WindowEvent ((Window) awtComponent, id, opposite,
+					  oldState, newState));
+	    oldState = newState;
+	  }
+      }
+    else
+      q.postEvent (new WindowEvent ((Window) awtComponent, id, opposite));
   }
 }
Index: java/awt/Window.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/awt/Window.java,v
retrieving revision 1.31
diff -u -r1.31 Window.java
--- java/awt/Window.java	9 Oct 2003 00:26:29 -0000	1.31
+++ java/awt/Window.java	23 Oct 2003 22:04:42 -0000
@@ -144,13 +144,12 @@
   {
     this ();
 
-    if (owner == null)
-      throw new IllegalArgumentException ("owner must not be null");
-
-    parent = owner;
-
-    synchronized (owner.ownedWindows)
+    synchronized (getTreeLock())
       {
+	if (owner == null)
+	  throw new IllegalArgumentException ("owner must not be null");
+
+	parent = owner;
         owner.ownedWindows.add(new WeakReference(this));
       }
 
@@ -220,7 +219,7 @@
       addNotify();
 
     // Show visible owned windows.
-    synchronized (ownedWindows)
+    synchronized (getTreeLock())
       {
 	Iterator e = ownedWindows.iterator();
 	while(e.hasNext())
@@ -247,7 +246,7 @@
   public void hide()
   {
     // Hide visible owned windows.
-    synchronized (ownedWindows)
+    synchronized (getTreeLock ())
       {
 	Iterator e = ownedWindows.iterator();
 	while(e.hasNext())
@@ -280,7 +279,7 @@
   {
     hide();
 
-    synchronized (ownedWindows)
+    synchronized (getTreeLock ())
       {
 	Iterator e = ownedWindows.iterator();
 	while(e.hasNext())
@@ -292,11 +291,15 @@
 	      // Remove null weak reference from ownedWindows.
 	      e.remove();
 	  }
-      }
 
-    for (int i = 0; i < ncomponents; ++i)
-      component[i].removeNotify();
-    this.removeNotify();
+	for (int i = 0; i < ncomponents; ++i)
+	  component[i].removeNotify();
+	this.removeNotify();
+
+        // Post a WINDOW_CLOSED event.
+        WindowEvent we = new WindowEvent(this, WindowEvent.WINDOW_CLOSED);
+        getToolkit().getSystemEventQueue().postEvent(we);
+      }
   }
 
   /**
@@ -386,7 +389,7 @@
   public Window[] getOwnedWindows()
   {
     Window [] trimmedList;
-    synchronized (ownedWindows)
+    synchronized (getTreeLock ())
       {
 	// Windows with non-null weak references in ownedWindows.
 	Window [] validList = new Window [ownedWindows.size()];
@@ -479,7 +482,7 @@
    */
   public void addWindowFocusListener (WindowFocusListener wfl)
   {
-    AWTEventMulticaster.add (windowFocusListener, wfl);
+    windowFocusListener = AWTEventMulticaster.add (windowFocusListener, wfl);
   }
   
   /**
@@ -489,7 +492,7 @@
    */
   public void addWindowStateListener (WindowStateListener wsl)
   {
-    AWTEventMulticaster.add (windowStateListener, wsl);  
+    windowStateListener = AWTEventMulticaster.add (windowStateListener, wsl);  
   }
   
   /**
@@ -497,7 +500,7 @@
    */
   public void removeWindowFocusListener (WindowFocusListener wfl)
   {
-    AWTEventMulticaster.remove (windowFocusListener, wfl);
+    windowFocusListener = AWTEventMulticaster.remove (windowFocusListener, wfl);
   }
   
   /**
@@ -507,7 +510,7 @@
    */
   public void removeWindowStateListener (WindowStateListener wsl)
   {
-    AWTEventMulticaster.remove (windowStateListener, wsl);
+    windowStateListener = AWTEventMulticaster.remove (windowStateListener, wsl);
   }
 
   /**
@@ -532,7 +535,9 @@
     // Make use of event id's in order to avoid multiple instanceof tests.
     if (e.id <= WindowEvent.WINDOW_LAST 
         && e.id >= WindowEvent.WINDOW_FIRST
-        && (windowListener != null 
+        && (windowListener != null
+	    || windowFocusListener != null
+	    || windowStateListener != null
 	    || (eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0))
       processEvent(e);
     else
@@ -565,39 +570,51 @@
    */
   protected void processWindowEvent(WindowEvent evt)
   {
-    if (windowListener != null)
+    int id = evt.getID();
+
+    if (id == WindowEvent.WINDOW_GAINED_FOCUS
+	|| id == WindowEvent.WINDOW_LOST_FOCUS)
+      processWindowFocusEvent (evt);
+    else if (id == WindowEvent.WINDOW_STATE_CHANGED)
+      processWindowStateEvent (evt);
+    else
       {
-        switch (evt.getID())
-          {
-          case WindowEvent.WINDOW_ACTIVATED:
-            windowListener.windowActivated(evt);
-            break;
-          case WindowEvent.WINDOW_CLOSED:
-            windowListener.windowClosed(evt);
-            break;
-          case WindowEvent.WINDOW_CLOSING:
-            windowListener.windowClosing(evt);
-            break;
-          case WindowEvent.WINDOW_DEACTIVATED:
-            windowListener.windowDeactivated(evt);
-            break;
-          case WindowEvent.WINDOW_DEICONIFIED:
-            windowListener.windowDeiconified(evt);
-            break;
-          case WindowEvent.WINDOW_ICONIFIED:
-            windowListener.windowIconified(evt);
-            break;
-          case WindowEvent.WINDOW_OPENED:
-            windowListener.windowOpened(evt);
-            break;
-          case WindowEvent.WINDOW_GAINED_FOCUS:
-          case WindowEvent.WINDOW_LOST_FOCUS:
-            processWindowFocusEvent (evt);
-            break;
-          case WindowEvent.WINDOW_STATE_CHANGED:
-            processWindowStateEvent (evt);
-            break;
-          }
+	if (windowListener != null)
+	  {
+	    switch (evt.getID())
+	      {
+	      case WindowEvent.WINDOW_ACTIVATED:
+		windowListener.windowActivated(evt);
+		break;
+
+	      case WindowEvent.WINDOW_CLOSED:
+		windowListener.windowClosed(evt);
+		break;
+
+	      case WindowEvent.WINDOW_CLOSING:
+		windowListener.windowClosing(evt);
+		break;
+
+	      case WindowEvent.WINDOW_DEACTIVATED:
+		windowListener.windowDeactivated(evt);
+		break;
+
+	      case WindowEvent.WINDOW_DEICONIFIED:
+		windowListener.windowDeiconified(evt);
+		break;
+
+	      case WindowEvent.WINDOW_ICONIFIED:
+		windowListener.windowIconified(evt);
+		break;
+
+	      case WindowEvent.WINDOW_OPENED:
+		windowListener.windowOpened(evt);
+		break;
+
+	      default:
+		break;
+	      }
+	  }
       }
   }
 
Index: jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMainThread.c
===================================================================
RCS file: /cvs/gcc/gcc/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMainThread.c,v
retrieving revision 1.8
diff -u -r1.8 gnu_java_awt_peer_gtk_GtkMainThread.c
--- jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMainThread.c	9 Oct 2003 00:26:29 -0000	1.8
+++ jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMainThread.c	23 Oct 2003 22:04:43 -0000
@@ -57,6 +57,8 @@
 jmethodID postItemEventID;
 jmethodID postListItemEventID;
 jmethodID postTextEventID;
+jmethodID postWindowEventID;
+
 JNIEnv *gdk_env;
 
 #ifdef PORTABLE_NATIVE_SYNC
@@ -163,6 +165,9 @@
 					  "postMouseEvent", "(IJIIIIZ)V");
   postConfigureEventID = (*env)->GetMethodID (env, gtkwindowpeer, 
 					  "postConfigureEvent", "(IIIIIIII)V");
+  postWindowEventID = (*env)->GetMethodID (env, gtkwindowpeer,
+					   "postWindowEvent",
+					   "(ILjava/awt/Window;I)V");
   postExposeEventID = (*env)->GetMethodID (env, gtkcomponentpeer, 
 					  "postExposeEvent", "(IIII)V");
   postKeyEventID = (*env)->GetMethodID (env, gtkcomponentpeer,
Index: jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c
===================================================================
RCS file: /cvs/gcc/gcc/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c,v
retrieving revision 1.8
diff -u -r1.8 gnu_java_awt_peer_gtk_GtkWindowPeer.c
--- jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c	9 Oct 2003 00:26:29 -0000	1.8
+++ jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c	23 Oct 2003 22:04:43 -0000
@@ -41,6 +41,23 @@
 #include "gnu_java_awt_peer_gtk_GtkFramePeer.h"
 #include <gdk/gdkprivate.h>
 #include <gdk/gdkx.h>
+#include <X11/Xatom.h>
+
+static void window_delete_cb (GtkWidget *widget, GdkEvent *event,
+			      jobject peer);
+static void window_destroy_cb (GtkWidget *widget, GdkEvent *event,
+			       jobject peer);
+static void window_show_cb (GtkWidget *widget, jobject peer);
+static gboolean window_focus_in_cb (GtkWidget * widget,
+				    GdkEventFocus *event,
+				    jobject peer);
+static gboolean window_focus_out_cb (GtkWidget * widget,
+				     GdkEventFocus *event,
+				     jobject peer);
+static gboolean window_window_state_cb (GtkWidget *widget,
+					GdkEvent *event,
+					jobject peer);
+static jint window_get_new_state (GtkWidget *widget);
 
 /*
  * Make a new window.
@@ -152,6 +169,25 @@
 
   connect_awt_hook (env, obj, 1, GTK_WIDGET (ptr)->window);
 
+  /* Connect signals for window event support. */
+  g_signal_connect (G_OBJECT (ptr), "delete-event",
+		    G_CALLBACK (window_delete_cb), obj);
+
+  g_signal_connect (G_OBJECT (ptr), "destroy-event",
+		    G_CALLBACK (window_destroy_cb), obj);
+
+  g_signal_connect (G_OBJECT (ptr), "show",
+		    G_CALLBACK (window_show_cb), obj);
+
+  g_signal_connect (G_OBJECT (ptr), "focus-in-event",
+		    G_CALLBACK (window_focus_in_cb), obj);
+
+  g_signal_connect (G_OBJECT (ptr), "focus-out-event",
+		    G_CALLBACK (window_focus_out_cb), obj);
+
+  g_signal_connect (G_OBJECT (ptr), "window-state-event",
+		    G_CALLBACK (window_window_state_cb), obj);
+
   gdk_threads_leave ();
 }
 
@@ -301,4 +337,155 @@
   gdk_threads_leave ();
 
   return height;
+}
+
+static void
+window_delete_cb (GtkWidget *widget __attribute__((unused)),
+		  GdkEvent *event __attribute__((unused)),
+		  jobject peer)
+{
+  (*gdk_env)->CallVoidMethod (gdk_env, peer,
+			      postWindowEventID,
+			      (jint) AWT_WINDOW_CLOSING,
+			      (jobject) NULL, (jint) 0);
+}
+
+static void
+window_destroy_cb (GtkWidget *widget __attribute__((unused)),
+		   GdkEvent *event __attribute__((unused)),
+		   jobject peer)
+{
+  (*gdk_env)->CallVoidMethod (gdk_env, peer,
+			      postWindowEventID,
+			      (jint) AWT_WINDOW_CLOSED,
+			      (jobject) NULL, (jint) 0);
+}
+
+static void
+window_show_cb (GtkWidget *widget __attribute__((unused)),
+		jobject peer)
+{
+  (*gdk_env)->CallVoidMethod (gdk_env, peer,
+			      postWindowEventID,
+			      (jint) AWT_WINDOW_OPENED,
+			      (jobject) NULL, (jint) 0);
+}
+
+static gboolean
+window_focus_in_cb (GtkWidget * widget __attribute__((unused)),
+		    GdkEventFocus *event __attribute__((unused)),
+		    jobject peer)
+{
+  /* FIXME: when hiding then showing, we get two sets of
+     (LOST_FOCUS/DEACTIVATED, ACTIVATED/GAINED_FOCUS) events. */
+  (*gdk_env)->CallVoidMethod (gdk_env, peer,
+			      postWindowEventID,
+			      (jint) AWT_WINDOW_ACTIVATED,
+			      (jobject) NULL, (jint) 0);
+
+  (*gdk_env)->CallVoidMethod (gdk_env, peer,
+			      postWindowEventID,
+			      (jint) AWT_WINDOW_GAINED_FOCUS,
+			      (jobject) NULL, (jint) 0);
+  return TRUE;
+}
+
+static gboolean
+window_focus_out_cb (GtkWidget * widget __attribute__((unused)),
+		     GdkEventFocus *event __attribute__((unused)),
+		     jobject peer)
+{
+  (*gdk_env)->CallVoidMethod (gdk_env, peer,
+			      postWindowEventID,
+			      (jint) AWT_WINDOW_LOST_FOCUS,
+			      (jobject) NULL, (jint) 0);
+
+  (*gdk_env)->CallVoidMethod (gdk_env, peer,
+			      postWindowEventID,
+			      (jint) AWT_WINDOW_DEACTIVATED,
+			      (jobject) NULL, (jint) 0);
+  return TRUE;
+}
+
+static gboolean
+window_window_state_cb (GtkWidget *widget,
+			GdkEvent *event,
+			jobject peer)
+{
+  jint new_state;
+
+  /* Handle WINDOW_ICONIFIED and WINDOW_DEICONIFIED events. */
+  if (event->window_state.changed_mask & GDK_WINDOW_STATE_ICONIFIED)
+    {
+      /* We've either been iconified or deiconified. */
+      if (event->window_state.new_window_state & GDK_WINDOW_STATE_ICONIFIED)
+	{
+	  /* We've been iconified. */
+	  (*gdk_env)->CallVoidMethod (gdk_env, peer,
+				      postWindowEventID,
+				      (jint) AWT_WINDOW_ICONIFIED,
+				      (jobject) NULL, (jint) 0);
+	}
+      else
+	{
+	  /* We've been deiconified. */
+	  (*gdk_env)->CallVoidMethod (gdk_env, peer,
+				      postWindowEventID,
+				      (jint) AWT_WINDOW_DEICONIFIED,
+				      (jobject) NULL, (jint) 0);
+	}
+    }
+
+  /* Post a WINDOW_STATE_CHANGED event, passing the new frame state to
+     GtkWindowPeer. */
+  new_state = AWT_FRAME_STATE_NORMAL;
+
+  if (event->window_state.new_window_state & GDK_WINDOW_STATE_ICONIFIED)
+    new_state |= AWT_FRAME_STATE_ICONIFIED;
+
+  new_state |= window_get_new_state (widget);
+
+  (*gdk_env)->CallVoidMethod (gdk_env, peer,
+			      postWindowEventID,
+			      (jint) AWT_WINDOW_STATE_CHANGED,
+			      (jobject) NULL, new_state);
+  return TRUE;
+}
+
+static jint
+window_get_new_state (GtkWidget *widget)
+{
+  GdkDisplay *display = gtk_widget_get_display(widget);
+  jint new_state = AWT_FRAME_STATE_NORMAL;
+  Atom type;
+  gint format;
+  gulong atom_count;
+  gulong bytes_after;
+  Atom *atom_list = NULL;
+  gulong i;
+
+  XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (widget->window),
+		      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
+		      0, G_MAXLONG, False, XA_ATOM, &type, &format, &atom_count,
+		      &bytes_after, (guchar **)&atom_list);
+
+  if (type != None)
+    {
+      Atom maxvert = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_VERT");
+      Atom maxhorz	= gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_HORZ");
+
+      i = 0;
+      while (i < atom_count)
+        {
+	  if (atom_list[i] == maxhorz)
+	    new_state |= AWT_FRAME_STATE_MAXIMIZED_HORIZ;
+          else if (atom_list[i] == maxvert)
+	    new_state |= AWT_FRAME_STATE_MAXIMIZED_VERT;
+
+          ++i;
+        }
+
+      XFree (atom_list);
+    }
+  return new_state;
 }
Index: jni/gtk-peer/gtkpeer.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/jni/gtk-peer/gtkpeer.h,v
retrieving revision 1.8
diff -u -r1.8 gtkpeer.h
--- jni/gtk-peer/gtkpeer.h	9 Oct 2003 00:26:29 -0000	1.8
+++ jni/gtk-peer/gtkpeer.h	23 Oct 2003 22:04:43 -0000
@@ -347,6 +347,23 @@
 #define AWT_FOCUS_LOST 1004
 #define AWT_FOCUS_GAINED 1005
 
+#define AWT_WINDOW_OPENED 200
+#define AWT_WINDOW_CLOSING 201
+#define AWT_WINDOW_CLOSED 202
+#define AWT_WINDOW_ICONIFIED 203
+#define AWT_WINDOW_DEICONIFIED 204
+#define AWT_WINDOW_ACTIVATED 205
+#define AWT_WINDOW_DEACTIVATED 206
+#define AWT_WINDOW_GAINED_FOCUS 207
+#define AWT_WINDOW_LOST_FOCUS 208
+#define AWT_WINDOW_STATE_CHANGED 209
+
+#define AWT_FRAME_STATE_NORMAL 0
+#define AWT_FRAME_STATE_ICONIFIED 1
+#define AWT_FRAME_STATE_MAXIMIZED_HORIZ 2
+#define AWT_FRAME_STATE_MAXIMIZED_VERT 4
+#define AWT_FRAME_STATE_MAXIMIZED_BOTH 6
+
 #define AWT_STYLE_PLAIN  0
 #define AWT_STYLE_BOLD   1
 #define AWT_STYLE_ITALIC 2
@@ -364,6 +381,8 @@
 extern jmethodID postItemEventID;
 extern jmethodID postListItemEventID;
 extern jmethodID postTextEventID;
+extern jmethodID postWindowEventID;
+
 extern jmethodID syncAttrsID;
 extern jclass gdkColor;
 extern jmethodID gdkColorID;

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