This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
[gui][patch] filter out one set of window focus events
- From: Thomas Fitzsimmons <fitzsim at redhat dot com>
- To: libgcj patches <java-patches at gcc dot gnu dot org>
- Date: Thu, 11 Mar 2004 18:59:58 -0500
- Subject: [gui][patch] filter out one set of window focus events
Hello,
I committed the attached patch to java-gui-branch.
We were receiving two sets of focus-in and focus-out events whenever a
top-level window gained or lost focus. The two sets of events were
coming from the window manager. When a top-level window becomes active,
the window manager first gives it the input focus by calling
XSetInputFocus. Then the window manager sends the WM_TAKE_FOCUS client
message to the window.
The WM_TAKE_FOCUS message tells the client that it may transfer focus
from the top-level window to one of the sub-windows within the
top-level. Usually GTK handles this message by transferring focus from
the top-level itself to its "default" widget -- that is, the widget that
will be activated when the user presses Enter.
The AWT has its own focus subsystem so we don't want GTK to handle
WM_TAKE_FOCUS, though we may want to handle it ourselves eventually. In
the meantime this patch filters the message out completely.
Tom
2004-03-11 Thomas Fitzsimmons <fitzsim@redhat.com>
* jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c
(window_wm_protocols_filter): New function.
(window_focus_in_cb): Remove function.
(window_focus_out_cb): Likewise.
(window_focus_or_active_state_change_cb): New function.
(create): Add filter that removes WM_TAKE_FOCUS client messages.
(connectSignals): Don't attach handlers to focus-in-event or
focus-out-event signals. Handle notify signal.
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.24
diff -u -r1.24 gnu_java_awt_peer_gtk_GtkWindowPeer.c
--- jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c 29 Jan 2004 14:34:31 -0000 1.24
+++ jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c 11 Mar 2004 23:28:30 -0000
@@ -44,6 +44,12 @@
#include <gdk/gdkx.h>
#include <X11/Xatom.h>
+static int filter_added = 0;
+
+static GdkFilterReturn window_wm_protocols_filter (GdkXEvent *xev,
+ GdkEvent *event,
+ gpointer data);
+
static void window_get_frame_extents (GtkWidget *window,
int *top, int *left,
int *bottom, int *right);
@@ -59,12 +65,9 @@
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 void window_focus_or_active_state_change_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ jobject peer);
static gboolean window_window_state_cb (GtkWidget *widget,
GdkEvent *event,
jobject peer);
@@ -147,6 +150,20 @@
insets[2] = bottom;
insets[3] = right;
+ /* We must filter out WM_TAKE_FOCUS messages. Otherwise we get two
+ focus in events when a window becomes active and two focus out
+ events when a window becomes inactive. */
+ if (!filter_added)
+ {
+ GdkAtom wm_protocols_atom =
+ gdk_x11_xatom_to_atom (gdk_x11_get_xatom_by_name ("WM_PROTOCOLS"));
+
+ gdk_add_client_message_filter (wm_protocols_atom,
+ window_wm_protocols_filter,
+ NULL);
+ filter_added = 1;
+ }
+
gdk_threads_leave ();
(*env)->ReleaseIntArrayElements (env, jinsets, insets, 0);
@@ -251,11 +268,8 @@
g_signal_connect (G_OBJECT (ptr), "show",
G_CALLBACK (window_show_cb), *gref);
- g_signal_connect (G_OBJECT (ptr), "focus-in-event",
- G_CALLBACK (window_focus_in_cb), *gref);
-
- g_signal_connect (G_OBJECT (ptr), "focus-out-event",
- G_CALLBACK (window_focus_out_cb), *gref);
+ g_signal_connect (G_OBJECT (ptr), "notify",
+ G_CALLBACK (window_focus_or_active_state_change_cb), *gref);
g_signal_connect (G_OBJECT (ptr), "window-state-event",
G_CALLBACK (window_window_state_cb), *gref);
@@ -661,40 +675,37 @@
(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)
+static void
+window_focus_or_active_state_change_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ 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;
+ if (!strcmp (g_param_spec_get_name (pspec), "is-active"))
+ {
+ if (GTK_WINDOW (widget)->is_active)
+ (*gdk_env)->CallVoidMethod (gdk_env, peer,
+ postWindowEventID,
+ (jint) AWT_WINDOW_GAINED_FOCUS,
+ (jobject) NULL, (jint) 0);
+ else
+ (*gdk_env)->CallVoidMethod (gdk_env, peer,
+ postWindowEventID,
+ (jint) AWT_WINDOW_DEACTIVATED,
+ (jobject) NULL, (jint) 0);
+ }
+ else if (!strcmp (g_param_spec_get_name (pspec), "has-toplevel-focus"))
+ {
+ if (GTK_WINDOW (widget)->has_toplevel_focus)
+ (*gdk_env)->CallVoidMethod (gdk_env, peer,
+ postWindowEventID,
+ (jint) AWT_WINDOW_ACTIVATED,
+ (jobject) NULL, (jint) 0);
+ else
+ (*gdk_env)->CallVoidMethod (gdk_env, peer,
+ postWindowEventID,
+ (jint) AWT_WINDOW_LOST_FOCUS,
+ (jobject) NULL, (jint) 0);
+ }
}
static gboolean
@@ -820,4 +831,17 @@
(jint) extents[1]); /* right */
return FALSE;
+}
+
+static GdkFilterReturn
+window_wm_protocols_filter (GdkXEvent *xev,
+ GdkEvent *event __attribute__((unused)),
+ gpointer data __attribute__((unused)))
+{
+ XEvent *xevent = (XEvent *)xev;
+
+ if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name ("WM_TAKE_FOCUS"))
+ return GDK_FILTER_REMOVE;
+
+ return GDK_FILTER_CONTINUE;
}