#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);
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);
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);
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);
(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
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;
+}